Untitled-10 1 6/6/12 11:32 AM VisualStudioMagazine.com

Windows 8 play nice with HTML5, JavaScript and CSS3.

PLUS Silverlight PivotViewer WPF Programming with C# 5.0 WCF Routing Primer Volume 22, No. 9 Volume SEPTEMBER 2012 Start a Revolution Refuse to choose between desktop and mobile.

With the brand new NetAdvantage for .NET, you can create awesome apps with killer data visualization today, on any platform or device. Get your free, fully supported trial today! www.infragistics.com/NET

Infragistics Sales US 800 231 8588 • Europe +44 (0) 800 298 9055 • India +91 80 4151 8042 • APAC (+61) 3 9982 4545 Copyright 1996-2012 Infragistics, Inc. All rights reserved. Infragistics and NetAdvantage are registered trademarks of Infragistics, Inc. The Infragistics logo is a trademark of Infragistics, Inc. All other trademarks or registered trademarks are the respective property of their owners.

Untitled-6 2 7/10/12 4:03 PM Compatible with ® Visual Studio® 2012

Untitled-6 3 7/10/12 4:04 PM Untitled-1 1 10/11/11 11:43 AM { FRAMEWORKS }

12

Keith Ward, Editor in Chief, Visual Studio Magazine Prepping for the Future You know, of course, that is just about here. But your shop is still making its money by building desktop/laptop software. What do you do? You might do what Adage Technologies September 2012 // Volume 22 // No. 9 is doing. This Chicago-based outfi t, started in 1999, continues to churn out line-of- business (LOB) apps as its bread and butter. FEATURES But, says Pat Emmons, cofounder and director of professional services, Adage is 12 Windows 8 Apps with HTML5 If you’re an experienced Web developer, you’ll love the HTML5/JavaScript/CSS3 also dipping its toe in the Windows 8 waters. options provided by Visual Studio 2012. Here’s a step-by-step guide to getting For a traditional code-focused company started. BY MICHAEL CRUMP like his, one of the major changes is the emphasis on design. Previously, Emmons Semantic Zoom with Silverlight 5 PivotViewer 18 says, “We thought our code carried the day.” The Silverlight 5 PivotViewer allows you to create unique and interactive data visualizations for your users. Find out how to effectively use this technology and Not so with Windows 8. “You make design incorporate semantic zoom into your data collections. BY TONY CHAMPION a big part of it from the beginning,” he adds. It’s a far cry from 6, which Adage used for years. “The shift to XAML has LANGUAGE LAB been a big learning curve. It’s kind of like the 28 PRACTICAL .NET anti-Visual Basic 6,” Emmons says. Many of Ensuring WCF Routing Flexibility the programs written in Visual Basic 6 look Windows Communication Foundation routing lets you decouple service consumers the same, he explains, but that “function and providers so you can modify and extend services without disrupting your clients. over form” mindset is becoming obsolete. BY PETER VOGEL Windows 8, Emmons says, is “all about 34 On VB branding and the UI experience.” That AOP with PostSharp comes through in the Windows 8 Aspect-oriented programming has the potential to help every developer write marketing-speak: “I’ve been doing higher-quality code in less time. Here’s how to declaratively apply custom methods [Microsoft-focused development] since to your code. BY JOE KUNK 1995, and ‘fast and fl uid’ was never part of 40 UI Code Expert the conversation,” he says. WPF Programming with C# 5.0 Now it’s the conversation, and requires Two new features of C# 5.0 can significantly improve your Windows Presentation attitude adjustments. “You can do so much Foundation UI programming. BY MARK MICHAELIS with [Windows 8] that it’s hard to get started,” he says. A developer can no longer DEPARTMENTS “just grab a button and throw it on the page.” Even though Adage’s core business will Letters to the Editor 6 be its LOB apps for the near future, 8 DevInsights VSTOOLBOX, PAPA’S PERSPECTIVE Emmons knows that change is a-comin’, VSToolbox: Comprehensive Testing with Test Studio PAGE 8 and he intends to see that his company is Papa’s Perspective: A Unified Approach to Client-Side Storage PAGE 10 on board, starting with Windows 8. But that’s not a bad thing. “That’s the COLUMNS awesomeness of the tech environment,” he says. “There’s always this rebirth.” 3 Frameworks BY KEITH WARD

BY ANDREW J. BRUST COVER ILLUSTRATION BY SHUTTERSTOCK.COM/VSM STAFF SHUTTERSTOCK.COM/VSM BY ILLUSTRATION COVER 48 Redmond Review

VisualStudioMagazine.com · September 2012 · VISUAL STUDIO MAGAZINE 3 Online Contents

Get the complete picture —the latest dev news, analysis and REDDEVNEWS.COM ADTMAG.COM

how-to content—at .NET ORMs Map New Direction Amazon Releases AWS VisualStudioMagazine.com in Wake of Visual Studio 2012 Cloud Security Practices BY KATHLEEN RICHARDS BY JEFFREY SCHWARTZ and our partner sites One of the beefs about the Microsoft While many cloud services providers have in the Redmond object-relational mapping tool, the Entity been reluctant to publicly disclose details Framework (EF), is its lack of extensibility. that would better explain how they secure Developer Network. That might change with EF 6 now that and ensure availability of their datacenters, Microsoft has open-sourced the code some have pointed to Amazon Web on CodePlex. Services (AWS) as the most distinguished holdout. Amazon took an important EASY FINDIT RedDevNews.com/Richards073112 What we once called FindIT codes are now easy step toward discrediting that claim by documenting its security practices. URLs. You’ll see these embedded throughout Microsoft Announces BUILD 2012 Visual Studio Magazine so you can access any BY KATHLEEN RICHARDS ADTmag.com/Schwartz073112 additional information quickly. Simply type in This year’s conference will start on Oct. 30, VisualStudioMagazine.com/ followed by the FindIT code into your URL address field. less than a week after Windows 8 is New Analyst Report Rips Agile scheduled to be released worldwide. In BY DAVID RAMEL addition to Windows 8 development, this In a brand-new report, analyst fi rm year’s event will offer sessions on Windows Voke Inc. claims: “The Agile movement Azure, Windows Phone 8, Windows Server is designed to sell services.” The 2012 and Visual Studio 2012. researchers analyze the movement and present their fi ndings about Agile use. RedDevNews.com/Richards072512 ADTmag.com/Ramel071312 VISUALSTUDIOMAGAZINE.COM Microsoft Updates Developer Preview of Cloud Identity Management Service Sun Veterans Create SDK The Builder Pattern in .NET BY KURT MACKIE for Native Java on the iPhone BY ERIC VOGEL Microsoft has enhanced the June developer BY JOHN K. WATERS The Builder software design pattern preview of Windows Azure Active Directory Codename One is developing a new SDK is commonly used to break up the with two additions aimed at opening up to allow Java developers to create native construction of a complex object. Eric Vogel the service to third-party developers. apps for mobile platforms, including iOS, covers the basic concepts and walks you Android, BlackBerry and Windows Phone. through the implementation in C#. RedDevNews.com/Mackie071712 ADTmag.com/Waters072512 VisualStudioMagazine.com/Vogel071612

ID Statement Visual Studio Magazine (ISSN 1537-002X) is published monthly by 1105 Media, Inc., 9201 Oakdale Avenue, Ste. 101, TFS Heads to the Clouds Chatsworth, CA 91311. Periodicals postage paid at Chatsworth, CA 91311-9998, and at additional mailing offi ces. Complimentary BY MICKEY GOUSSET subscriptions are sent to qualifying subscribers. Annual subscription rates payable in U.S. funds for non-qualifi ed subscribers are: U.S. $35.00, International $60.00. Annual digital subscription rates payable in U.S. funds for non-qualifi ed subscribers are: U.S. $25.00, With the 2012 release, Microsoft is adding International $25.00. Subscription inquiries, back issue requests, and address changes: Mail to: Visual Studio Magazine, P.O. Box a new way of consuming Team Foundation 2166, Skokie, IL 60076-7866, email [email protected] or call toll free (888) 768-8759, fax number 847-763-9564. Interna- tional calls 847-763-9135. POSTMASTER: Send address changes to Visual Studio Magazine, P.O. Box 2166, Skokie, IL 60076-7866. Server (TFS). Team Foundation Service Canada Publications Mail Agreement No: 40612608. Return Undeliverable Canadian Addresses to Circulation Dept. or XPO Returns: provides access to the features you’ve P.O. Box 201, Richmond Hill, ON L4B 4R5, Canada. come to expect without having to install Copyright Statement © Copyright 2012 by 1105 Media, Inc. All rights reserved. Printed in the U.S.A. Reproductions in whole or and manage the actual application on-site. part prohibited except by written permission. Mail requests to “Permissions Editor,” c/o Visual Studio Magazine, 230 California St. Suite 302, San Francisco, CA 94111. VisualStudioMagazine.com/Gousset071812 Legal Disclaimer The information in this magazine has not undergone any formal testing by 1105 Media, Inc. and is distributed without any warranty expressed or implied. Implementation or use of any information contained herein is the reader’s sole responsibility. While the information has been reviewed for accuracy, there is no guarantee that Disabling Design Time Data the same or similar results may be achieved in all environments. Technical in a Windows Phone Application inaccuracies may result from printing errors and/or new developments in the industry.

BY NICK RANDOLPH Corporate Address 1105 Media, 9201 Oakdale Ave. Ste 101, Chatsworth, CA 91311 www.1105media.com Mobile Corner columnist Nick Randolph Media Kits Direct your Media Kit requests to Matt Morollo, VP Publishing, 508-532-1418 (phone), shows you how to effectively disable the 508-875-6622 (fax), [email protected] design time data in your Windows Phone Reprints For single article reprints (in minimum quantities of 250-500), e-prints, plaques and posters contact: application at runtime, without sacrifi cing PARS International Phone: 212-221-9595 E-mail: [email protected] www.magreprints.com/QuickQuote.asp the designer experience in Expression Blend. List Rental This publication’s subscriber list, as well as other lists from 1105 Media, Inc., is available for rental. For more information, VisualStudioMagazine.com/Randolph072312 please contact our list manager, Merit Direct. Phone: 914-368-1000; E-mail: [email protected]; Web: www.meritdirect.com.

4 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-7 1 12/8/11 3:10 PM For 2012, we’ll be in Orlando, Fla., Letters in December! VisualStudioMagazine.com September 2012 • Volume 22 • No. 9

Agile Rebellion Editorial Staff In a recent blog post, “Is Agile Really a ‘Developer Rebellion Against Unwanted Editor in Chief Keith Ward Tasks’?” (VisualStudioMagazine.com/Ramel071712), Data Driver blogger David Ramel Executive Editor Kathleen Richards Group Managing Editor Wendy Hernandez wrote about the mixed reaction from developers to his article about a controversial Associate Managing Editor Katrina Carrasco report on Agile software development from analyst firm Voke Inc. “Many people still Tools Editor Peter Vogel seem unclear as to what Agile actually is,” he observed. Several readers agreed, and some didn’t. Here’s a sampling of their responses. Contributing Editors Andrew J. Brust, Ian Davis, Mickey Gousset, Joe Kunk, Mark Michaelis, John Papa, I’m in my second position that claimed to be using “Agile.” My experience has Nick Randolph, Patrick Steele, Eric Vogel been that Agile is an excuse to not think things through and not document Art Staff requirements. My current boss says things like, “My ideas are lumps of clay ... Creative Director Scott Shultz they’re not fully formed.” Yeah, thanks a lot, Agile, for making me do all the design Art Director Joshua Gould Production Staff and run around getting feedback from all the stakeholders on how something Director, Print Production Jenny Hernandez-Asandas should actually function. I’m not saying you need to defi ne things down to the Production Coordinator Serena Barnes smallest detail, but a little up-front thought and architecture goes a long way Online/Digital Media toward making better code and better products in the long run. Sr. Director, Online Media Becky Nagel Hero Executive Editor, New Media Michael Domingo Site Administrator Shane Lee Posted Online Designer Rodrigo Muñoz

Advertising/Sales I’m really surprised by the report and lack of consensus among the developer VP/Group Publisher Matt Morollo crowd. To me it’s bad news—the level of general ignorance goes up, and people Regional Sales Manager Chris Kourtoglou simply don’t read anything anymore. I’ll insist that reading a Wikipedia defi nition National Accounts Director William Smith National Account Manager/ Danna Vedder is enough to understand on a basic level the difference between an Agile and a Microsoft Account Manager non-Agile way of developing software. Agile is the result of decades of software development experience by a myriad of . Many of its premises are not new and are proven by hard facts. So the real problems, I think, are ignorance, President Henry Allain VP, New Content Initiatives Doug Barney inability to change and fear of failure. Sr. Director of Marketing Michele Imgrund Yuri Sokolovski & Audience Engagement Director of Online Marketing Tracy Cook Posted Online

New Designer for Android President & Neal Vitale for Android columnist Wallace McClure took the new Designer for Chief Executive Offi cer Senior Vice President Richard Vitale Android for a spin and offered some tips in his online column, “Xamarin Designer for & Chief Financial Offi cer Android” (VisualStudioMagazine.com/McClure0612). Readers welcomed the addition of a Executive Vice President Michael J. Valenti design surface. Vice President, Christopher M. Coates Finance & Administration Vice President, Erik A. Lindgren Yes, yes and yes! I fi nd I’m constantly frustrated by overly feature-rich toolsets that Information Technology don’t explain a damn thing. Then they wonder why adoption is so low, especially & Application Development Vice President, David F. Myers by new coders. A designer does a great service in bridging the gap between Event Operations toolset and coder knowledge. Why all tools don’t include it, I will never understand. Chairman of the Board Jeffrey S. Klein Tom Posted Online REACHING THE STAFF Staff may be reached via e-mail, telephone, fax, or mail. A list of editors and contact information is also available online Great article—I think this really helps reduce the barrier to entry over porting .NET at VisualStudioMagazine.com. E-mail: To e-mail any member of the staff, please use the code to the Mono/Android platform. Thanks for this—I didn’t know it existed. following form: [email protected]. Robert Irvine Offi ce (weekdays, 9:00 a.m. - 5:00 p.m. PT) Telephone 949-265-1520; Fax 949-265-1528 Canada 4 Venture, Suite 150, Irvine, CA 92618 Framingham Offi ce (weekdays, 9:00 a.m. - 5:00 p.m. ET) Telephone 508-875-6644; Fax 508-875-6633 600 Worcester Road, Suite 204, Framingham, MA 01702 Visual Studio Magazine wants to hear from you! Send us your thoughts Corporate Offi ce (weekdays, 8:30 a.m. - 5:30 p.m. PT) Telephone 818-814-5200; Fax 818-734-1522 about recent stories, technology updates or whatever’s on your mind. 9201 Oakdale Avenue, Suite 101, Chatsworth, CA 91311 E-mail us at [email protected] and be sure to include your first and last name, city and state. Please note that letters may be edited Visual Studio Magazine for form, fit and style. They express the views of the individual authors, and The opinions expressed within the articles and other contents herein do not necessarily express those of the publisher. do not necessarily reflect the views of the VSM editors or 1105 Media Inc.

6 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Connect legacy technologies affordably with the complete set of data integration tools from Altova®

Experience how the Altova MissionKit®, the integrated suite of XML, data mapping, and database tools, can help you leverage existing technology and business software investments while integrating modern technologies – without breaking your budget.

The Altova MissionKit includes NEW in Version 2012: multiple intelligent tools for data integration: 4USFBNJOHSFBEJOHXSJUJOH ® of files for large-scale MapForce – Graphical data mapping, ETL applications transformation, & conversion tool r4PSUJOHPGEBUBNBQQJOH Drag-and-drop data conversion with instant results r transformation & code gen r/FXEBUBQSPDFTTJOH functions r Support for mapping XML, DBs, EDI, r+%#$ESJWFST JOBEEJUJPO Excel®, XBRL, flat files & Web services  UP"%0BOE0%#$ ® r/FX OBUJWF+BWB"1*T XMLSpy – XML editor and Web services tool r XML editor with strong database integration r Web services tool, JSON <> XML converter DatabaseSpy® – multi-database query, design & comparison tool r Support for all major relational databases and translation between DB types r SQL editor, graphical database design & content editor

Download a 30 day free trial!

Try before you buy with a free, fully functional trial from www.altova.com

Scan to learn more about data integration with the MissionKit.

Untitled-2 1 7/6/12 3:45 PM

Test Studio

Telerik Inc. VSToolbox Web: telerik.com Phone: 888-365-2779 Price: $2,499 for a single license with Comprehensive Testing with Telerik one year of upgrades and support Quick Facts: A comprehensive test Test Studio suite that covers UI, load and Test Studio brings together the tools to fully test your applications—provided your performance testing team is willing to make the commitment to using it. Pros: A well-designed UI integrates the testing tools that mission-critical applications require BY PETER VOGEL in a perfect world, you do), then you’ll Cons: Unlike test-driven develop- When “Shōgun” (Delacorte Press, 1975) need a virtual user pack, but you’ll have to ment, taking advantage of Test Telerik Telerik surpassed 1,100 pages, someone observed call Telerik to get a quote on the price. Test Studio Test Studio requires a commitment from that it wasn’t a novel, it was a summer Finally, if you’re going to commit to Test the organization and integration vacation. The same could be said about Studio, you’ll want to make sure that you’re into the development process Telerik Test Studio because it’s not just a taking full advantage of it, so you’ll also be tool—it’s a team commitment. Test Studio interested in Telerik’s training packages. isn’t a replacement for Visual Studio The studio’s integration of functional, support for test-driven development. It’s an Well-Crafted UI load and performance tests will be integrated, standalone package that operates Fortunately, the well-crafted Test Studio UI attractive to shops already executing at a whole other level, assuming you want reduces the barriers to entry in creating testing at the level that Test Studio assumes. to go there—and in a perfect world, you do. and managing tests. In Test Studio, you can Test Studio brings together a variety of Test Studio is aimed at small to mid-level start creating an automated Web, Windows tools that are often sold separately. You can, shops, and despite the strong integration, it Presentation Foundation (WPF) or load for instance, run your UI-based tests as doesn’t require Visual Studio. Be warned: test with a right-click (manual tests are also load tests or performance tests. The range This isn’t a cheap package. At $2,500 per integrated into the test plan). You can write of application types covered is also seat, you’re not going to buy a license for your tests by specifying actions Web, WPF attractive: WPF, ASP.NET and, in the every developer. Instead, you need someone and load tests; or you can record your mobile arena, iOS. in your team to be your test manager/Test interactions with your application and save In addition to the standalone UI, the Test Studio resource. In addition to buying Test it as a test (your actions are tied to specific Studio suite includes a set of services that Studio, you’ll probably want the runtime elements in your application’s UI rather provide the input data for some of the tests. version to use on test servers (at $199 each, than mouse movements or keyboard Test Studio also includes a Visual Studio the runtimes are relatively inexpensive). If navigation). For Web-based applications, plug-in and a set of templates for creating you intend to do load testing (and, again, you can import logs to create a test. test projects. The integration with Visual Studio is good, allowing you to do your bug tracking either with Visual Studio Team Foundation Server or Telerik Team Pulse. Like many developers, I’m suspicious of tools designed to support automated UI testing: the scripts for UI testing are often too complicated to maintain as applications evolve. The Telerik scripts, however, are tied to page elements rather than mouse movements. That should make your tests more resilient, provided you have the discipline and planning to avoid renaming your elements or drastically rearranging your UI. As I said, adopting a testing tool like this is as much about commitment as anything else. VSM

Peter Vogel is the Visual Studio Magazine tools To generate a functional test, start recording from within a Telerik Test project, navigate to editor and a principal at PH&V Information your Web page and work through your tests. Services, specializing in ASP.NET development.

8 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-1 1 8/9/12 12:05 PM

Papa’sPerspective BY JOHN PAPA A Unified Approach to Client-Side Storage This simple API can give you a leg up on local storage in your Web apps.

after all. Local storage is ideal for retaining { name: 'John', age: 34, pets: [{name: data that either doesn’t change often (you 'Fido', type: 'dog'}, can set expiration dates), or to help maintain {name: 'Tink', type: 'cat'}]}, state across pages, tabs and browser sessions. { name: 'Landon', age: 14, pets: [{name: Say you’re building a Web app that 'Iron Man', type: 'dog'}, supports multiple versions of different {name: 'McQueen', type: 'dog'}]}]; Local Storage Local browsers. You want to use localStorage You can store these objects using where available, but also fall back and amplify.store by passing a key value, provide graceful degradation in older followed by the textVal object. Amplify.store browsers. What do you do? Certainly not a will serialize the data in testVal, do a check lot of conditional logic—bleh! for localStorage support (and fallback, if necessary), then store the data.The data Unifi ed API with Amplify.store can be retrieved using the same store This is the sweet spot for AmplifyJS, a method, by only passing a key value. You of jQuery components built by the can also clear the storage by passing a null Web apps, generally, have sets of data that folks at appendTo LLC. It includes three in for the value. either don’t change a whole lot, or that main features: AJAX requests, pub/sub represent state—the configuration, content messaging and storage. The amplify.store Examining Local Storage and attributes—which must be maintained object provides a unified way to persist You can examine what’s currently in local between page calls. HTTP offers a variety data from a variety of Web browsers. It storage by calling amplify.store and passing of great features, but state has to be reset offers a single API across multiple no parameters. If you want to know which between page calls because it’s stateless. So browsers, which implement storage quite key values are being stored, you could also where do you store that data in Web differently. The amplify.store library hides run a script. You can clear a data value applications? The concept of local storage the complexity and logic, so you can focus from local storage immediately by calling addresses this challenge quite nicely. on storing and retrieving data—and not on amplify.store(key, null) or setting an how to handle it in different browsers. You expiration on the data when you store it. Why Use Storage? can find a complete list of the amplify.store Simply pass an optional parameter to the Local storage in HTML5 refers specifically default storage mechanisms based on store method following the data value. The to the localStorage object. I recommend browser support at bit.ly/OxoyY4. parameter is an object containing an using it if you’re building an app for an Note: If your browser doesn’t support expiration value in milliseconds. HTML5-compliant browser that implements JSON2, you must include JSON2.js as well. The simplicity of the API, its support for localStorage. (You can check the popular This is required in 7 and the localStorage object and its graceful site, caniuse.com, to see if your browsers earlier versions to use the JSON.stringify degradation make this one of my favorite support localStorage and other features.) and JSON.parse methods. APIs for this space. All of the sample code Historically, browsers have used a variety Local storage stores a key value pair, can be found in this fiddle, which uses of techniques to store local data, including where the key and the value are both toastr (bit.ly/IphVJ1) to display the values localStorage, sessionStorage (which differs strings. What this means is that if you want and log the storage and retrieval: jsfiddle.net/ from localStorage in that its data goes away to store arrays and objects, you should johnpapa/zsQZN. VSM when the browser closes), globalStorage, serialize them first, using JSON.stringify cookies and userData. (and de-serialize them with JSON.parse). John Papa is a Microsoft regional director and You can use cookies, but there are some However, if you use amplify.store, it will former Microsoft technical evangelist. He specializes limitations, which Christian Heilmann serialize and de-serialize the data to and in professional application development with explains in his article, “Local Storage and from JSON for you. Windows, HTML5, JavaScript, CSS, Silverlight, How to Use It on Web Sites” (bit.ly/s0DVDY). The following sample code defines an Windows Presentation Foundation, C#, .NET and It’s worth noting that while you can store a array of people objects: SQL Server. Check out his online training with lot of data in local storage, you should use var testKey = 'people'; Pluralsight or find him at johnpapa.net and this feature judiciously—it’s not a database, var testVal = [ on Twitter at twitter.com/john_papa.

10 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-1 1 8/9/12 12:05 PM VSM COVER STORY

If you’re an experienced Web developer, you’ll love the HTML5/JavaScript/CSS3 options provided by Visual Studio 2012. Here’s a step-by-step guide to getting started. BY MICHAEL CRUMP ILLUSTRATION BY SHUTTERSTOCK.COM/VSM STAFF SHUTTERSTOCK.COM/VSM BY ILLUSTRATION

12 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com VSM COVER STORY

We now know that Windows 8 is coming on Listing 1. The default HTML page, with no additions. Oct. 26. That presents developers with a decision to make for building new Metro-style applications: HTML5 with JavaScript and CSS3, or XAML with C#, or Visual Basic with C++? VSMagJS Many Web developers will choose HTML5/JavaScript/CSS3 because they already have experience with it. Once that decision’s made, the next step is to understand (WinRT) and how its new APIs interact with Windows 8. [As this issue went to press, Microsoft was considering changing the name “Metro” to something else, but hadn’t yet decided on the new name. We’re leaving it as “Metro” until a new name is officially chosen.—Ed.] This article takes you through the process of building your first

Content goes here

HTML5/JavaScript/CSS3 Metro application. Let’s get started. Setting up the Environment Before getting started, you’ll need to download the following items: ■ Fixed-Layout App: A Metro project that scales a fixed-aspect ■ The Windows 8 release preview, which can be downloaded ratio layout. from the Windows 8 Download Center (bit.ly/MwBIKe). You ■ Navigation App: A Metro project with predefined navigation can run Windows 8 on actual hardware or install it onto a VM controls. or virtual hard disk. The optimal experience is gained with a touch-supported monitor. Components ■ The Visual Studio 2012 release candidate (RC) (bit.ly/LkKuIN), You’ll start with a blank template and add in the required function- which is required to build Metro apps. It comes with several ality as you go, rather than selecting a template with a lot of the templates to jump-start your dev efforts. In this article, we’ll plumbing already in place. This will better help you understand the specifically be reviewing the HTML5/Java Script/CSS3 templates. makeup of an HTML5/JavaScript/CSS3 Metro application. ■ I’d also recommend downloading the Metro app samples (bit.ly/ Once you become accustomed to building Metro applications, HsPXh3). Samples include new controls featured in WinRT; how feel free to try another template to speed up development. For now, to work with tap gestures; device orientation and much more. select the “Blank Application” template and give it a name such as The samples pack is licensed for public use, so feel free to use it VSMagJS, then press OK. in your own applications. It’s available in a number of languages: Once the Visual Studio 2012 RC loads, take a look at the Solution C++, C#, JavaScript and Visual Basic .NET. Explorer on the right. First, I’ll give some details on the various files: Begin by launching the Visual Studio 2012 RC from the Metro ■ References: Contains the dependent WinRT API references Start screen and selecting Templates/Other Languages/JavaScript/ needed for this application to function. Notice that only one is Windows Metro style. added by default: the Library for JavaScript Here are the templates that ship out of the box: 1.0 RC. This includes both the dark and light CSS files, as well ■ Blank App: A single-page project for a Metro app that has no as the base API files needed for WinRT. It also includes global predefined controls or layout. string files for the English language in this case. ■ Grid App: A multipage Metro project that navigates among ■ CSS: The default.css file is simple; it only contains CSS3 media groups of items. Dedicated pages display group and item details. queries to determine device orientation. ■ Split App: A two-page Metro project that navigates among ■ Images: This folder contains four images used for the logos to grouped items. The first page allows group selection, while the represent your application. It also contains the splashscreen, second displays an item list alongside details for the selected item. which is displayed upon your application’s startup.

Figure 1. The first Metro application using Figure 2. The updated application with the Figure 3. The application using the light theme. HTML5/JavaScript/CSS3. click event.

VisualStudioMagazine.com · September 2012 · VISUAL STUDIO MAGAZINE 13 COVER STORY Windows 8 Applications

Table 1. Package.appxmanifest category descriptions.

Tab Name Description

Use this page to set the properties that identify and Application UI describe your app. Use this page to specify system features or devices your Capabilities application can use. Use this page to add declarations and specify their Declarations properties. Use this page to confi gure URIs that have access to Content URIs Web standards for geolocation and clipboard access. Use this page to set the properties that identify and Packaging describe your package once deployed.

Starting from the top, you can see the application uses the HTML5 doctype and other standard HTML tags such as meta and title. Moving down the page, you’ll see the WinJS references to the WinRT API. The next set of references is specific to your application. Figure 4. The package.appxmanifest describes the application’s Again, the default.css is just handling orientation, and the default.js deployment package. will be covered shortly. Everything else is standard HTML you’re ■ JS: Includes one file—default.js—that runs when your application used to seeing, from a body paragraph to a closing HTML tag. starts. It contains boilerplate code to get you started quickly. It’s time to modify the default.html page by replacing the body ■ Default.html: The standard HTML page where you’ll add with the following code: your code for a UI. ■ Package.appxmanifest: Describes the deployment package for

Hello, VSM Reader

your application and allows you to make changes to capabilities,

What's your favorite magazine?

declarations and so forth. You’ll dive into each tab later. ■ VSMagJS_TemporaryKey.pfx: A Personal Information Exchange File—in other words, a digital certificate for this application.
Modifying the Start Page If you run the application by pressing the “Local Machine” button Let’s begin by taking a look at the default.html page that comes from the debug toolbar, you should see Figure 1 (p. 13). with the template. It’s shown in Listing 1 (p. 13). There’s one small problem—nothing happens when entering data or clicking the button. This is where you need to dive into the default.js file and add logic to UI. Listing 2. The default JavaScript fi le. (function () { Adding Logic to the Start Page "use strict"; You’ve defined a UI, but it doesn’t respond to a user’s actions just yet. var app = WinJS.Application; For that, you’ll need to take a look at the default.js file provided by var activation = Windows.ApplicationModel.Activation; the blank template (see Listing 2) and add some custom code. WinJS.strictProcessing(); To begin, you can see that default.js is wrapping itself in a self- app.onactivated = function (args) { executing anonymous function. This helps avoid naming conflicts if (args.detail.kind === activation.ActivationKind.launch) { or a situation where you didn’t intend to modify a value. Next up, if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } };

app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). };

app.start(); })(); Figure 5. Creating the app package to deploy to the Windows Store or a local machine.

14 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-5 1 7/10/12 11:26 AM COVER STORY Windows 8 Applications

There’s one small problem—nothing happens when entering data or clicking the button. This is where you need to dive into the default.js fi le and add logic to UI.

underneath app.oncheckpoint. (Refer to the complete default.js shown in Listing 3, opposite page.) Here’s the function: function OKbuttonClickHandler(eventInfo) { var answer = document.getElementById("magazineInput").value; if (answer == 'Visual Studio Magazine') { var finalanswer = "Good Answer!"; } else { var finalanswer = "Try Again! - Hint type Visual Studio Magazine"; } document.getElementById("questionOutput").innerText = finalanswer; } With the addition of this function, you’ve defined a local variable— answer—that gets the value set in our magazineInput input tag. Once you have the value, check to see if the user typed “Visual Studio Magazine.” Then either “Good Answer!” or “Try Again! - Hint type Visual Studio Magazine” is displayed in the questionOutput div tag. The completed default.js is shown in Listing 3. Figure 6. Creating the app package for local distribution, as opposed Go ahead and run the application, entering the value “Visual to the Windows Store. Studio Magazine.” Figure 2 (p. 13) should be the result. note the strict keyword provides additional error checking for your As you can tell from Figure 2, the application displayed the output code. Scrolling down, you’ll see the application becomes activated in your div defined in default.html. Entering anything else will get and several TODOs, which include what code to run from a fresh you the message “Try Again! - Hint type Visual Studio Magazine.” start or suspended state. There’s also a placeholder for adding code when the application’s about to be suspended. Styling Your Application Quickly and Easily Now you’ll wire in some code to make the default.html page One of the most important concepts you can learn when working functional. Locate the following line: with Metro is the difference between styles supplied out of the box by args.setPromise(WinJS.UI.processAll()); Microsoft. By default, the dark style is applied in the default.html file Underneath it, add the following three lines of code: by this line: // Get the Element ID of our OK Button and attach an event handler to it. var OKButton = document.getElementById("questionButton"); The Metro UI supplies a light theme as well. By simply changing OKButton.addEventListener("click", OKbuttonClickHandler, false); one line of code in the default.html, your UI reacts accordingly: Start by getting the Element ID of your OK button defined in default.html and adding a simple event handler to it. Even though Go ahead and switch back over to default.html and change that you’re building an HTML5 Metro application, you’re free to use line from ui-dark.css to ui-light.css and run the application again. popular JavaScript libraries such as jQuery to simplify code. In this The application should look like Figure 3 (p. 13). instance, you’re simply waiting on a click event of the OK button. Notice how the background changed to white and the text to Next, you need to add a function called OKbuttonClickHandler black, the input tag now has a nice gray border around it, and the to run code once the OK button has been clicked. Add this function button is clearly visible. This was accomplished with only one slight change to an HTML file.

Explore More Now it’s time to explore the package.a- ppxmanifest further. As discussed earlier, the package.appxmanifest describes the deployment package for your application. You can access it by double-clicking the file, but under the covers it’s simply an XML file. Open it to see the screenshot in Figure 4 (p. 14). Each page provides access to Figure 7. Installing the application with the local deployment option in Visual Studio 2012. specific functionality that your

16 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com COVER STORY

Even though you’re building an HTML5 Metro application, you’re free to use popular JavaScript libraries such as jQuery to simplify code.

application may or may not need. Each tab is explained in Table 1, p. 14 to target (if your target application is set to Release mode prior to (and more information is available in the MSDN help documentation). running the wizard; by default it’s set to debug). Clicking Create presents a package you can sideload onto another Packaging Your App machine by simply selecting the Add-AppDevPackage file and using Now that you’ve built your app, you can distribute it by navigating the context menu to Run with PowerShell. This installs the applica- through Project/Store/Create App Package…, as shown in Figure 5 (p. tion on the end-user machine, as shown in Figure 7 (opposite page). 14). The distribution options are the Windows Store or local (known as sideloading), as shown in Figure 6 (opposite page). For this, you’ll Only the Beginning create a local package, as the Windows Store is not publicly open yet. What you’ve done in building this application is just the beginning In most circumstances, you’ll distribute through the Windows Store. of the possibilities of Metro. Microsoft has provided a rich API that After hitting the Next button, you have the option to save the most developers will embrace, while continuing to use their existing files as well as set the version number and what platform you wish skillset. So keep exploring Windows 8 Metro, because the future of computing has changed, and your abilities need to keep pace. VSM Listing 3. The modifi ed default.js code, adding a click event. (function () { Michael Crump is a Microsoft MVP, INETA Community Champion and an "use strict"; author of several .NET books. He speaks at a variety of conferences and has var app = WinJS.Application; written dozens of articles on .NET development. He currently works at var activation = Windows.ApplicationModel.Activation; Telerik Inc. as a XAML evangelist. You can follow Crump on Twitter at WinJS.strictProcessing(); twitter.com/mbcrump or keep up with his blog by visiting michaelcrump.net. app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll());

// Get the Element ID of our OK Button and attach an event handler to it. var OKButton = document.getElementById("questionButton"); OKButton.addEventListener("click", OKbuttonClickHandler, false);

} };

app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). };

function OKbuttonClickHandler(eventInfo) {

var answer = document.getElementById("magazineInput").value; if (answer == 'Visual Studio Magazine') { var finalanswer = "Good Answer!"; } else { var finalanswer = "Try Again! - Hint type Visual Studio Magazine "; } document.getElementById("questionOutput").innerText = finalanswer; }

app.start(); })();

VisualStudioMagazine.com · September 2012 · VISUAL STUDIO MAGAZINE 17 Application, as shown in Viewer control. Unlike previous the version, PivotViewer isnow If you’ve spent muchtime Each user inadomain user Each willhave hisown of idea how download the developer tools at data-visualization control calledthePivotViewer wasamong the cation by File, selecting New and Project from theVisual Studio only required installations are 2010SP1 and cover fundamentals the of using PivotViewer and show you how to enable usersto visualizecollections of data inan interactive way. on Silverlight the technology, Zoom Deep PivotViewer allows you to control, PivotViewer thebar sets indata visualization by providing control to your project. To addareference to PivotViewer, the entirely contained ina single DLL, making it to easier addthe Because the PivotViewer the Because isnow of apart Silverlight the SDK, the Creating aPivotViewerApplication users’ requirements can around become visualization. data should sorted, filtered be and displayed. menu. After Newthe Project dialog is displayed, a Silverlight select 8 VISUAL STUDIOMAGAZINE 18 allows to users not only create customized of views adata but set, an intuitive client-side interface for and sorting filtering data, and additions to theplatform. PivotViewer allows you to build solutions have inmore missed been traditional formats. In article, this I’ll applications, thenyou’re painfully aware of how complex the Microsoftthe Silverlight 5Tools for Visual Studio 2010SP1. You can to discover trends and relationships within the data that might presenting two data distinct with views different zoom levels. Built that empower to users create own their vision of data. their incorporate Semantic into Zoom your data collections. W When Microsoft released Silverlight 2011,anew 5inDecember This type ofThis type data visualization presents a unique solution that Once you installed, have create everything aSilverlight 5appli- Originally developed by Live asastandalone Labs Silverlight 4 For project, this only the reference you needto Pivot- addisthe S S P FEATURE data visualizations for your users. Findouthowtoeffectivelyusethistechnology data visualizationsforyourusers. E I I I The Silverlight5PivotViewerallowsyoutocreate uniqueandinteractive M V T L Figure 1 and incorporatesemanticzoomintoyourdatacollections. · September 2012 · (p. 22). bit.ly/L6nvlg A V H O writing data-driven . N T E · VisualStudioMagazine.com 2 BY TONY CHAMPION V R T 4 L I I 1 The first order of business isto create aclass inyour project that will you must first addaPivotViewer to project. the isa this Because you’re ready to build aPivotViewer application. Extensible Markup Language original (CXML,the PivotViewer will rotate through each member of wait the Dinner- Thefinal staff. arandomwill be number 1and between 5;and table assignments Party class isshown in PivotViewer object. Thefirst step isto openMainPage.xaml the PivotViewer example, application’s the UIwillconsist solely of a each property uniquely data the so issomewhat meaningful to test collection of 100DinnerParty should objects. Thismethod handle create DinnerParty inthe astatic method class that willreturn a ect andect Add, select then Class. Once the Add New Item dialog screen contain statistics. dinnerparty the Right-click on Silverlight the proj- during a single in a shift restaurant. ItemsSource property (one of most requested the features after the data, properties and templates. other Like Silverlight item controls, data—the sample (found code download code inthe and available data source), Data Open Protocol (OData) or Rich Internet Appli- cation (RIA) services. release of original the version). With feature, this you’re able to use right-click References Silverlight inthe project and addareference sample data on client the at runtime. To accomplish you this, need against. For example, each party will get a unique Id; the SizeOfParty appears, name class the DinnerParty.cs. Thenfollowing add the any that method you to obtain choose data, it’s whether Collection a collection of data can addedto be PivotViewer by setting the at at Defi properties to class: the Id, StaffName, TimeSeated and SizeOfParty. to define a data class—in this case, statistics adata case, onto class—intable define this each of diners to System.Windows.Controls.Pivot. Now project the up, isset and You needonly three things to create aPivotViewer application: In order to generate acollection of data for example, this you’ll In order on to PivotViewer—instead focus the of on obtaining Before generated adding newly the data to PivotViewer, the VisualStudioMagazine.com/Champion0912 ning aDataClass E C I 1 W G 2 3 Listing 1 H E Z 2 (p. 20). O R T ) isgoing to generate some 1 O 3 1 1 M 5 4 2

ILLUSTRATION BY RYANVSM STAFF ETTER Untitled-2 1 8/6/12 4:08 PM FEATURE PivotViewer

Built on the Silverlight Deep Zoom technology, PivotViewer allows you to enable users to visualize collections of data in an interactive way.

and add a namespace to System.Windows.Controls.PivotViewer. set, so they appear in the filter pane. In addition, the StaffName has Next, add an instance of the PivotViewer to the Grid control and the CanSearch option set, so you can search features of PivotViewer name it pViewer: to look up a particular staff member. Designing the trading cards is often the biggest challenge for The last step is to assign the ItemsSource property of pViewer to our developers. Let’s face it: This jumps into the design world. In order generated collection. Open up the codebehind file, MainPage.xaml.cs. to design an effective trading card, it’s important to understand the In the constructor, you can now add the generated data: data you’re displaying and what’s important to the user. Designed public MainPage() correctly, the trading cards can add an extra dimension to the data { that enables users to visually identify relationships and trends. InitializeComponent(); Size is an important design concept to keep in mind. When you’re pViewer.ItemsSource = DinnerParty.BuildData(); looking at an entire collection containing 1,000 items, each trading } After defining the data source for this example, you must define the properties PivotViewer will display. This is accomplished by Listing 1. The DinnerParty class. setting the PivotViewerProperties property to a collection of Pivot- public class DinnerParty ViewerProperty objects. There are four different PivotViewerProperty { public int Id { get; set; } classes that are available: public string StaffName { get; set; } ■ PivotViewerDateTimeProperty public DateTime TimeSeated { get; set; } public int SizeOfParty { get; set; } ■ PivotViewerLinkProperty

■ PivotViewerNumericProperty public static ObservableCollection BuildData() ■ PivotViewerStringProperty { The purpose of a PivotViewerProperty is to add to var data = new ObservableCollection(); each property that you wish to display inside PivotViewer and tell var rdm = new Random(); var startDt = new DateTime(2012, 4, 1, 18, 0, 0); it how you want the data to be treated. PivotViewer will only display for (int i = 0; i < 100; i++) data for the properties you define. If your object has 20 properties { and you only define four, then you’ll only see those four within the var itm = new DinnerParty() { Id = i };

PivotViewer UI. var mod = i % 3; A PivotViewerProperty is defined by a unique name, a display name, a binding statement that maps it to your object, and one or switch (mod) { more options. Each option defines how the PivotViewerProperty case 0: will be used within the PivotViewer. The following list includes the itm.StaffName = "Jane Doe"; available options and explains how they’re handled by PivotViewer: break; case 1: ■ CanFilter: Adds the property to the filter panel and the itm.StaffName = "John Smith"; sort dropdown break; ■ CanSearchText: Allows the property to be searched case 2: itm.StaffName = "Suzie Q"; ■ None: Does not add a property to the UI break; ■ Wrapping Text: Wraps the text of the property when } displaying it in the detail pane Next, add all four properties to the PivotViewerProperties collection. itm.SizeOfParty = rdm.Next(1, 5); itm.TimeSeated = startDt.AddMinutes(rdm.Next(1, 240)); You can define these properties in XAML or code. Listing 2 (p. 22) data.Add(itm); shows the complete XAML for declaring the PivotProperties. For Id } and SizeOfParty, use a PivotViewerNumericProperty. TimeSeated is a return data; PivotViewerDateTimeProperty, and StaffName is a PivotViewerString- } } Property. All of the properties except for Id have the CanFilter option

20 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-1 1 5/10/12 12:20 PM FEATURE PivotViewer

Listing 2. The XAML to create PivotViewer and Listing 3. Value converter to convert StaffName defi ne properties. to a SolidColorBrush. public class StaffNameValueConverter : IValueConverter { { color = Color.FromArgb(255, 98, 62, 188); case "Suzie Q": return new SolidColorBrush(color); }

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) card will be very small. Because the purpose of the trading card is { to convey information to the user, it’s only possible to present one throw new NotImplementedException(); or two pieces of information. Any more than that and the cards will } } be too cluttered for the user to distinguish between them. As the size of the cards gets larger on the screen, there’s more real estate available to add information for the user. Ideally, you’d like to present question: How do you show the StaffName? If you print the Staff- a more detailed card as the user zooms in closer and increases the Name on the card, it will be unreadable when you zoom out to view size of the trading card on the screen. the entire collection. This is where visualization comes into play. For example, in our sample data collection, the StaffName and The No. 1 question I get asked about using PivotViewer is, “What SizeOfParty are two important pieces of information that stand out. happens if I don’t have any pictures in my data?” Some developers The first trading card will focus on these two properties. The trading feel that this will prevent them from having a usable collection. This card itself will be a square. The SizeOfParty will be displayed in a notion couldn’t be further from the truth. Developers routinely large TextBlock that’s centered in the square. The only remaining present other forms of data visualization that don’t require images. When was the last time you needed a picture for each data point in a line or bar chart? It’s possible to present effective visualizations with a com- bination of text, color and icons. Not only can you make the trading cards visually appealing, but you can also use these tools to help the user identify trends and relationships among the displayed data set. Trying to visualize the StaffName property is a good example. If each staff member is represented by a different color and you set the background of each trading card to the color representing that staff member, then you have created a visualization that will make sense and is useful to the user. With a large number of trading cards, a user can look at the histogram of tables per hour and can visually determine which staff member had the most Figure 1. Creating a new Silverlight 5 application. tables for that time period.

22 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com OCR Module available v4.5! High-Performance PDF Printer Driver with royalty-free licensing! ■ Create accurate PDF documents in a fraction of the time needed with other tools ■ WHQL tested for all Windows 32 and 64-bit platforms ■ Produce fully compliant PDF/A documents ■ Standard PDF features included with a number of unique features ■ Interface with any .NET or ActiveX programming language

PDF Editor for .NET, now Webform Enabled v4.5! The new OCR Module from Amyuni ■ Edit, process and print PDF 1.7 documents programmatically enables developers to: ■ Fast and lightweight 32 and 64-bit managed code assemblies ■ Convert non-searchable PDF files into for Windows, WPF and Web applications searchable PDFs ■ Support for dynamic objects such as edit-fields and sticky-notes ■ Create searchable PDF documents out ■ Save image files directly to PDF, with optional OCR of various image formats such as multi- ■ Multiple image compression formats such as PNG, JBIG2 and TIFF page TIFF, JPEG or PNG while applying text recognition ■ Compress image based PDF documents using high compression JBIG2 or more New! PDF Integration into Silverlight Applications standard CCITT, JPEG and PNG ■ Server-side PDF component based on the robust Amyuni PDF compression formats Creator ActiveX or .NET components The Amyuni OCR module is based on the ■ Client-side C# Silverlight 3 control provided with source-code Tesseract Library with the Amyuni PDF ■ Optimization of PDF documents prior to converting them into XAML technology being used to process and ■ Conversion of PDF edit-boxes into Silverlight TextBox objects create the PDF documents. ■ Support for other document formats such as TIFF and XPS Learn more at www.amyuni.com More Development Tools Available at: www.amyuni.com

All trademarks are property of their respective owners. © 1999-2010 AMYUNI Technologies. All rights reserved. USA and Canada Europe Toll Free: 1 866 926 9864 Sales: (+33) 1 30 61 07 97 Support: (514) 868 9227 Support: (+33) 1 30 61 07 98 Info: [email protected] Customizations: [email protected]

Untitled-6 1 4/11/11 12:56 PM FEATURE PivotViewer

Running the project, the PivotViewer is loaded with 100 items displayed, as shown in Figure 2. You’re able to change the sort, filter the collection, and see the item details in the detail pane on the right-hand side when you select an item. It’s important to remember that all of this functionality came out of the box. All that’s required is to supply the data, and describe what to show and how to show it. The first thing that should catch your eye is the division of tiles between all three of our staff members. Even with the sim- plistic trading cards, it’s possible to begin inferring data relationships. For example, sorting by “Staff Name” and selecting the histogram view will show that each staff member has roughly the same number of tables in the system. Sorting by “Size of Party” in the histogram view lets you visualize which staff members had the Figure 2. Screenshot of PivotViewer displaying an entire collection. larger or smaller parties. It should quickly become evident that this approach to data Implementing Value Converters analysis can be useful to the user given properly designed cards. The best way to accomplish this visualization is with a value converter. By creating a value converter that converts a StaffName string to a Using Semantic Zoom SolidColorBrush, you’ll be able to bind the trading card’s background Another improvement in the latest release of PivotViewer is the con- to the StaffName. Start by adding a new class to the project named cept of Semantic Zoom. Semantic Zoom is the ability to create different StaffNameValueConverter.cs. The class should inherit the IValue- visualizations based on the size of an item. This lets you change the Converter interface. Visual Studio will add the code necessary to level of detail that the user sees as he zooms closer to an item. implement this interface for you. This can be done by right-clicking If you take a look at the current example, not a lot of detail is IValueConverter and selecting Implement Interface. shown once you select a trading card. To take full advantage of the The IValueConverter interface has two methods: Convert and PivotViewer, you should provide more information as the user ConvertBack. The Convert property receives the raw value in a zooms in closer to a trading card. The solution is to add a second binding statement and lets you convert it into something different. trading card with more details to the PivotViewer. For this example, it takes the StaffName string and returns a Solid- Before adding a second template to the ItemTemplates collection, ColorBrush based on that string. In this instance, it isn’t necessary it’s necessary to take a closer look at the PivotViewer workflow to write an implementation for the ConvertBack because the binding with regard to item templates. The PivotViewerItemTemplate has a doesn’t need to convert from a color back to the StaffName. MaxWidth property. This property is important to the workflow. Listing 3 (p. 22) shows an implementation of a value converter When a trading card is rendered, the first template in the collection that will map the staff names to unique colors. The method contains is used to render the card. If the MaxWidth property is set on the a switch statement that will map each of the three names of the staff members to a unique color. While a more flexible converter would need to be created in a real-world solution, this is suitable for dem- Listing 4. Initial PivotViewer item template. onstrating how to visualize a textual property. Before you can use the new value converter an instance of it must be added to your XAML. The first thing to add is a new namespace to the UserControl: xmlns:local="clr-namespace:VSM_PivotViewer" by adding a resource to the UserControl: FontSize="90" FontWeight="Bold" Foreground="White" HorizontalAlignment="Center" Once the StaffNameValueConverter code is completed, you can VerticalAlignment="Center" /> create the first PivotViewerItemTemplate and add it to the Item- Templates property, as demonstrated in Listing 4. As previously mentioned, the template will only contain a Grid and a TextBlock. The Grid’s Background property is bound to the StaffName property ... removed for brevity using the StaffNameValueConverter. The TextBlock has its Text property bound to the SizeOfParty property.

24 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-2 1 8/6/12 4:22 PM FEATURE PivotViewer

Listing 5. Detailed PivotViewer item template. HorizontalAlignment="Center" FontSize="90" VerticalAlignment="Bottom" HorizontalAlignment="Center"/> ... removed for brevity template, then once the trading card is wider in screen pixels than If you take a look at what this second template provides you, you that value, the PivotViewer moves to the next card in the collection. should begin to see the power of Semantic Zoom. Effectively, utilizing This process continues until the correct size is found, or there are this approach allows you to bring another dimension to your users. no more templates to check. If this happens, the trading card won’t Imagine if you only used a single template in your collection. be generated and a blank image will be rendered to the screen. You’d have to take one of two approaches. The first would be to use In order to present the user with more information, Listing 5 shows a simplistic card, as in the original collection. This would give you an updated ItemTemplates property for the PivotViewer. The tem- the ability to create graphical correlations between data points, but plate adds more details from our data set. For instance, both the staff overall it would be lacking in details about a single data point. If you name and the time the table was seated are displayed on the card. went the other direction and created a single detailed card, all of The template is added after the first template, so the PivotViewer your cards would look identical when viewing the entire collection. will still load the original template first. Before the new template This would hinder your ability to show relationships between data. is used by the PivotViewer, you must first set a MaxWidth to the In addition, you’d take a performance hit by attempting to render original template. Listing 5 shows how the original template was mod- an entire collection with a complex template. ified to define a MaxWidth equal to 300. Running the app will generate With the enhancements in the latest version of the PivotViewer, the same view as the first example. However, once you zoom in closer it’s now conceivable to give the user the ability to choose which to the cards, the cards will change to the new, more detailed template templates to use and how those templates are defined. A single as shown in Figure 3. If you zoom in slowly enough, you’ll also notice interface could be used in completely different ways to display data. that the PivotViewer creates a smooth transition between the two The PivotViewer API allows you to set things like the current viewer, templates by blending in the new template over the original. the filter state and the sorting property via code. Therefore, you can store this information for the user and restore settings for future sessions. The Silverlight 5 PivotViewer has come a long way since the original version. Its client- side XAML-based rendering, dynamic updates and enhanced API provide a solid foundation for creating interactive and informative data visualizations. Adding the PivotViewer to your apps will give your users a completely new way to experience their data and allow them to explore it in ways not previously possible. VSM

Tony Champion is a MVP. He founded Champion DS, which specializes in .NET, XAML, HTML5 and SharePoint consulting. Find him on his blog at tonychampion.net or on Twitter at twitter.com/tonychampion.

GO ONLINE Go to VisualStudioMagazine.com/Champion0912 to read Figure 3. Creating a second, more detailed PivotViewer item template. this article online and download the sample code.

26 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Orlando, FL December 10-14 Royal PaciÀ c Resort at Universal Orlando | vslive.com/orlando Who Should Attend? ³ Developers

³ Software Architects

³ Programmers

Visual Studio Live! provides ³ Designers

education and training on what’s ³ IT Professionals

now, new and next on the .NET ³ IT Managers

development platform. ³ Consultants Session Topics Include:

³ HTML5

³ Mobile

³ Visual Studio / .NET

³ Windows 8 / WinRT

³ WPF / Silverlight

³ XAML

Save Up To $400! Register Before October 10 Use Promo Code DEVVSS vslive.com/orlando

Buy 1 Event, Get 3 Free! Customize an agenda to suit your needs – access to all 4 Live! events is included in your registration. Attend just 1 conference or all 4 for the same price. { Visual Studio Live! is co-located with:

GOLD SPONSOR SUPPORTED BY MEDIA SPONSOR PRODUCED BY

Untitled-1 1 8/6/12 2:16 PM

IN THIS SECTION: Practical .NET · 28 // On VB · 34 // UI Code Expert · 40 /////////////

{ PRACTICAL .NET }

Ensuring WCF Routing doesn’t support message decomposition or combination. For instance, you can’t take an incoming request, break it down Routing Flexibility into two separate messages and send those messages to different Windows Communication Foundation routing lets you decouple methods on different services. Routing only supports redirecting your service consumers and providers to give you the fl exibility to to matching methods or operations on different services. modify and extend your services without disrupting your clients. BY PETER VOGEL Setting up Services WCF Routing WCF Assume, for instance, that you have an existing service (Customer- In designing service-oriented architectures Service) that many consumers already access. You’ve created a new (SOAs), you want to ensure that once version of the service (EnhancedService) at a new address. The consumers start accessing your services, new service includes an auditing feature in many of the service’s they can always access your service—despite operations (methods). Of course, to fully exploit the new feature, planned maintenance, server upgrades and consumers will have to rewrite their code (there’s a new parameter enhancements to the services themselves. they need to pass to the service’s methods). At the most basic level, this means that But in the meantime, even without consumers passing that once a service becomes available at a particular endpoint (URL or parameter, you’ll get some benefits from the new service if your TCP address), it remains available at that address despite any consumers can be persuaded to use it. Initially, the new service reorganizations of your datacenter and enhancements to the will be left in place at its old address—because you’d also like to service. An Enterprise Service Bus (ESB) can be a big help here, have the ability to switch back to that service if the new one turns but you can also use Windows Communication Foundation out to have problems. (WCF) routing to either address these same concerns or to The interfaces for the two services are shown in Listing 1. implement something your ESB doesn’t support. Routing redirects the existing service to the new service (and Routing allows you to provide a single, unchanging endpoint for switches back to the old service, if necessary) without disturbing your consumers to use—an endpoint that your services’ many your consumers. Later on, if the consumer authors wish, they can “real” endpoints can hide behind. This allows you to, for instance, rewrite their programs to supply the new parameter and take full relocate your services to a new address without your consumers advantage of the new service. having to change their endpoints. Routing also allows you to direct your consumers to a backup service when the primary service is unavailable, either by accident or intent. Routing also enables you to redirect service Listing 1. Interfaces for CustomerService and EnhancedService. requests originally targeted to an older version of your service namespace CustomerService to a new version of your service; again, without any change { [ServiceContract(Namespace="http://www.phvis.com/customermanagement")] to your consumers. public interface ICustomerService WCF 4 supports routing by letting you create a routing host. { The routing host provides a single point of contact to your [OperationContract] consumers. Routing is rules-based: in the host you build a table of CustomerInfrastructure.Customer GetCustomerById( string CustID); rules that specify how incoming requests are to be redirected. You } can update and modify that table over time as services become } available and need to be added to the table or are taken offline and need to be removed from the table. namespace EnhancedService { The router processes incoming requests according to those [ServiceContract(Namespace="http://www.phvis.com/customermanagement")] rules, connecting consumers to the appropriate services (and public interface ICustomerService routing outbound messages from the service back to the consumer). { [OperationContract(name="GetCustomerById")] WCF routing also supports multicasting—sending a single service CustomerInfrastructure.Customer AuditableGetCustomerById( request to multiple services, either for redundancy purposes or to string CustID, allow simultaneous processing by multiple services (for instance, string AuditCode); sending a customer complaint both to the quality-tracking service } } and the customer-management service).

28 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Orlando, FL December 10-14 Royal PaciÀ c Resort at Universal Orlando | splive360.com Who Should Attend? ³ SharePoint Administrators ³ Power Business Users ³ Managers SharePoint Live! provides training for ³ IT Pros those who must customize,deploy and ³ Developers maintain SharePoint Server and ³ Project Mangers SharePoint Foundation to maximize the business value. Both current & newly ³ Information Architects released versions will be covered! Session Topics Include: ³ Strategy, Governance, Adoption ³ Management and Administration ³ Information & Content Management ³ BI, BPA, Search, and Social ³ SharePoint and the Cloud ³ SharePoint 2010 & SharePoint 2013

Save Up To $400! Register Before October 10 Use Promo Code DEVSPS splive360.com

Buy 1 Event, Get 3 Free! Customize an agenda to suit your needs – access to all 4 Live! events is included in your registration. Attend just 1 conference or all 4 for the same price. { SharePoint Live! is Co-located with:

GOLD SPONSOR SUPPORTED BY MEDIA SPONSOR PRODUCED BY

Untitled-7 1 8/7/12 1:35 PM

{ PRACTICAL .NET }

For routing to work, the two services must “look alike,” at least the .NET-provided IRequestReplyRouter interface, so a good next to the outside world. My two sample interfaces are in different .NET step is to create a ContractDescription object you can use when namespaces (CustomerService and EnhancedService), but that’s creating the ServiceEndpoints: not a problem: the .NET namespace is private. However, their ContractDescription cdRouter = ContractDescription.GetContract( service namespaces (http://www.phvis.com/customermanagement) typeof(IRequestReplyRouter)); and interface/contract name (ICustomerService) are identical When creating a ServiceEndpoint object, you pass the Contract- because those are public (that is, they would be included in the Description you just created, the type of binding you want to use Web Services Description Language contract generated from with your service and an EndpointAddress object holding the this service). The interface’s method names are different address for the service. (GetCustomerById versus AuditableGetCustomerById). However, For the router’s ServiceEndpoint (the place where consumers by using the Name property on the OperationContract attribute will now send their messages), you can use any endpoint you wish. on the AuditableGetCustomerById method, their public names For the endpoint of the services to which you’re routing, you’ll are the same (GetCustomerById). Both methods return a need to use the endpoints they’ve assigned themselves in their Customer object; that Customer object must be from the same .config files (or that ASP.NET has assigned them, if your services .NET namespace in both versions of the service. are part of an ASP.NET project). The two methods also accept different parameter lists (one The following code creates the ServiceEndpoint for the router (at parameter in the original method, two parameters in the new one). port 9000) and the endpoint for one of the services being routed to In Web Services, though, .NET takes a devil-may-care attitude (at port 8000). The code for the other service’s ServiceEndpoint toward passing parameters, and happily discards extra parameters would be almost identical, with only the URL changing: WCF Routing WCF or provides default values to missing ones. So this isn’t a problem, ServiceEndpoint se = new ServiceEndpoint(cdRouter, either, provided you include code to handle missing values. new WSHttpBinding(), new EndpointAddress( Creating a Router "http://localhost:9000/CustomerService/")); Given two services that look alike, your next step is to create a service host that handles routing between the two services. In ServiceEndpoint MainService = new ServiceEndpoint(cdRouter, production, your routing host will probably be a Windows Service. new WSHttpBinding(), The following code would go in the Windows Service OnStart new EndpointAddress( method. For testing purposes, however, it’s easier to create a console "http://localhost:8000/MainService/CustomerService/")); application; I’ll be using this code in the console’s Main method. The router’s ServiceEndpoint gets special treatment—it’s added After adding a console application to the Visual Studio solution to the host’s ServiceEndpoint collection using the AddService- with the services that implement the interfaces, you need to add Endpoint method: application references to the Microsoft .NET Framework 4 System.S- host.AddServiceEndpoint(se); erviceModel and System.ServiceModel.Routing libraries. At the top of the project’s Program.cs file, you’ll also need these using directives: Defi ning Routing Rules using System.ServiceModel; The next step is to create a MessageFilterTable object that holds using System.ServiceModel.Description; the rules for redirecting requests made to the routing service to using System.ServiceModel.Dispatcher; the service the consumer actually wants. The MessageFilterTable using System.ServiceModel.Routing; holds an IEnumerable collection of ServiceEndpoints. Next, you’ll add the code to the Program.cs file’s Main method to Once the table is created, you add it to a RoutingConfiguration instantiate the ServiceHost using the .NET-provided RoutingService object, pass the RoutingConfiguration object to a RoutingBehavior class. The foreach loop in the code finds the ServiceDebugBehavior object and add the RoutingBehavior object to the host’s object that’s automatically added to your ServiceHost Behaviors Behaviors collection: collection, and sets it to return lots of detail in any error messages. MessageFilterTable> mft = While you need this for debugging during development, you’ll new MessageFilterTable>(); want to remove it when you move this code to the Windows RoutingConfiguration rc = new RoutingConfiguration(mft, false); Service you’ll use in production: RoutingBehavior rb = new RoutingBehavior(rc); ServiceHost host = new ServiceHost(typeof(RoutingService)); host.Description.Behaviors.Add(rb); foreach (var sb in host.Description.Behaviors) When adding the table to the RoutingConfiguration, you can { use the second parameter to specify whether routing rules apply ServiceDebugBehavior sdb = sb as ServiceDebugBehavior; only to the request’s header. This code specifies false, which allows if (sdb != null) me to route messages based on the content of the message (for { example, the parameters being passed to the service’s methods). sdb.IncludeExceptionDetailInFaults = true; With the table created and made available to the router, you can } populate the table with objects that inherit from the MessageFilter } class. Each variation on the MessageFilter class specifies criteria Your next step is to create ServiceEndpoint objects for each of for directing a request, and is added to the table with a collection the services involved in the process. In this example, there are of ServiceEndpoints. While the collection of ServiceEndpoints three endpoints: the service host (the router) and the two services associated with a filter will typically have only one entry, the ability to which it routes requests (CustomerService and EnhancedService). to add multiple endpoints lets you implement multicasting: one All three ServiceEndpoint objects need a contract that’s based on request sent to multiple services.

30 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Orlando, FL December 10-14 Royal PaciÀ c Resort at Universal Orlando | sqllive360.com Who Should Attend? ³ Database Professionals (DBAs) ³ Analytics Specialists SQL Server Live! provides comprehensive ³ Developers education on SQL Server database ³ IT Professionals management, data warehouse/BI ³ Consultants model design, Big Data, analytics, performance tuning, troubleshooting Session Topics Include: and coding against SQL Server. ³ BI and Big Data ³ Hadoop ³ T-SQL, SSIS Packages, Disaster Recovery ³ Monitoring, Maintaining, Tuning ³ SQL Azure & Windows Azure ³ SQL Server 2012

Save Up To $400! Register Before October 10 Use Promo Code DEVSQS sqllive360.com

Buy 1 Event, Get 3 Free! Customize an agenda to suit your needs – access to all 4 Live! events is included in your registration. Attend just 1 conference or all 4 for the same price. { SQL Server Live! is co-located with:

GOLD SPONSOR SUPPORTED BY MEDIA SPONSOR PRODUCED BY

Untitled-1 1 8/6/12 2:15 PM

{ PRACTICAL .NET }

The simplest MessageFilter is the MatchAllMessageFilter, which PROTOCOL CONVERSION redirects all requests to its endpoint. This code creates a List of I advise my service-oriented architecture (SOA) clients to create ServiceEndpoints and adds the ServiceEndpoint created earlier to focused services that refl ect design decisions around separation of the list. The code then creates a MatchAllMessageFilter and adds it, concerns and implementing the single responsibility principle. The with the List of ServiceEndpoints, to the MessageFilterTable: goal is to have well-focused services that communicate between each List primaryEndPoints = new List(); other to implement business processes. However, developers creating primaryEndPoints.Add(MainService); interoperable Web Services that can be accessed by a wide variety of MessageFilter mamf = new MatchAllMessageFilter(); consumers are justifi ably concerned that the cost of communicating mft.Add(mamf, primaryEndPoints); between the services (especially network latency) will result in When adding a MessageFilter to the table, you can specify a unacceptable performance. The obvious solution is to create mono- priority as the third parameter to the Add method. When a lithic services with all their related maintenance and testing issues. matching rule is found, no other rules at a lower priority will be Windows Communication Foundation routing provides a better examined. When you create the MessageFilterTable, you can solution. The routing host can accept interoperable Web Services specify the default priority for MessageFilters added without a requests (wsHttpBinding or basicHttpBinding) from external priority (if you don’t provide the value, the default priority is 0). consumers, but redirect those requests to internal services using much faster netTcpBinding. The SOA gets the best of both worlds: Exercising Your Router well-focused internal atomic services that communicate quickly, and The final step in your router is to open your service host wh en you interoperable Web Services that can be consumed by any client. In start up and close it when you’re done. In a Windows Service, the case study in this article, for instance, it would just be a matter of WCF Routing WCF you’d put the Open method call in the Windows Service OnStart switching the external CustomerService and EnhancedService over to method and the Close method call in the OnStop method. netTcpBinding to get a signifi cant performance improvement. —P.V. Because I’m using a console application here, I put in a WriteLine to notify me that the router’s ready and a ReadLine to hold my application in memory between the Open and Close: replace the CustomerService ServiceEndpoint added to the table host.Open(); with the EnhancedService ServiceEndpoint to which you want to Console.WriteLine("Router up"); redirect requests. You can do that without having to shut down the Console.ReadLine(); host by updating the list of service endpoints associated with the host.Close(); MessageFilter. This code, for instance, removes the ServiceEndpoint named MainService from the list of services used with my message Exercising the Rules filter and adds the ServiceEndpoint held in EnhancedService: To test your router, you’ll need to create a client program to call primaryEndPoints.Remove(MainService); operations on your service. You can use any project type you want (I primaryEndPoints.Add(BackupService); used a Windows Form), but you’ll need to add a Service Reference to the client project that points to one of the services your router More Rules works with (this will generate the proxy that your client needs). While I’ve used the MatchAllMessageFilter here, there are about a After adding the Service Reference, go into your client’s .config half-dozen more MessageFilters included in the .NET Framework 4. file and change the endpoint address from the service’s endpoint For instance, the ActionMessageFilter lets you redirect requests for to the endpoint you assigned to your router (http://localhost:9000/ specific methods or operations to a different service. This example CustomerService, in my example). would let me redirect requests to the GetCustomerById method to Before you can test your application, you’ll need to configure some other service with an identical method name: your startup projects. Right-click on your solution’s name in primaryEndPoints.Add(MainService); Solution Explorer and select Set StartUp Projects. In the resulting ActionMessageFilter amf = new ActionMessageFilter( dialog, select the Multiple Startup Projects choice and set the "http://www.phvis.com/customermanagement/ICustomerService/GetCustomerById"); Action for your routing host and client projects to Start. Use the up mft.Add(amf, primaryEndPoints); and down buttons to put your routing host first in the list. If none of the included MessageFilters meet your needs, you can build Unfortunately, unless you’re running under an Administrator your own custom MessageFilter on top of the base MessageFilter class. account, when you first test your application you’ll probably get an But the real issue is when you should do this: You should create error message indicating that you don’t have the necessary security the router as part of writing your service, so that you can pass your to access the service. router’s endpoint rather than the service’s endpoint to consumers The error message is actually pretty good: it tells you to use the (though, of course, moving an existing service to a new address netsh command-line utility, passing the specified endpoint and and assigning the router the service’s old address wouldn’t be too your login identity (domainname\username). To do that from awkward to implement). your Start menu, right-click on the Command Prompt and select Once consumers are accessing your services through your Run as Administrator. When the window opens, enter the netsh router, you can do whatever you need to behind the router. A little command as shown in the error message, inserting your domain- bit of preventative maintenance at the start will give you lots of name/username (if you’re not sure who you are, use the whoami flexibility at the end. VSM command to display your current identity). Everything should work the next time you test your application. Peter Vogel is a principal in PH&V Information Services, specializing in At this point the router is sending requests for the original service ASP.NET development with expertise in SOA, XML, database and UI design. to the original service—not much value added. The next step is to His blog on technical writing can be found at rtfmphvis.blogspot.com.

32 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Orlando, FL December 10-14 Royal PaciÀ c Resort at Universal Orlando | virtlive360.com Who Should Attend? ³ Developers ³ IT Professionals ³ IT Managers Cloud & Virtualization Live! is a ³ Systems Administrators new event that provides in-depth ³ Consultants training with real-world applicability Session Topics Include: on today’s cloud and virtualization ³ Becoming a Virtualization Expert technologies. ³ Constructing & Managing an Application Delivery Infrastructure ³ Integrating Mobile Devices and Consumerization with Cloud Computing ³ Managing the Modern Cloud Enabled Datacenter ³ Tactics in Cloud Application Development

Save Up To $400! Register Before October 10 Use Promo Code DEVCVS virtlive360.com

Buy 1 Event, Get 3 Free! Customize an agenda to suit your needs – access to all 4 Live! events is included in your registration. Attend just 1 conference or all 4 for the same price. { Cloud & Virtualization Live! is co-located with:

GOLD SPONSOR SUPPORTED BY MEDIA SPONSOR PRODUCED BY

Untitled-1 1 8/6/12 2:10 PM

{ ON VB }

AOP with PostSharp To be clear, the code for these crosscutting concerns is still Aspect-oriented programming has the potential to help every present in the application; it has simply been moved into aspects. developer write higher-quality code in less time. Here’s how to Writing these aspects generally requires a more experienced declaratively apply custom methods implementing common developer, so they tend to be high-quality code. These aspects are functionality to your code. added to the application by the AOP framework at specific BY JOE KUNK execution points known as “join points,” such as at the time of object instantiation, method initiation, method exit, property In a recent discussion with the applications access and so on. A set of join points is known as a pointcut. development manager of a major global company that uses the Microsoft .NET History of AOP Framework as its development platform, I AOP isn’t something recently created to help .NET developers. was asked how his department could Work on AOP started in the Xerox Palo Alto Research Center Programming (PARC) in 1996, which is the same group credited with giving us Aspect-Oriented Aspect-Oriented increase productivity. We discussed several approaches, including increased code reuse. laser printing; the Ethernet network protocol; the modern PC GUI That discussion led me to take a deeper look at aspect-oriented using windows, icons and a mouse; object-oriented programming programming (AOP). What I found is that AOP can increase code (OOP) via Smalltalk; and very-large-scale integration (VLSI) for reuse within targeted functional areas, while also improving code semiconductors. PARC research into AOP resulted in the design maintainability and readability. AOP has the potential to help of what is now AspectJ for the Java language. every developer write higher-quality code in less time. Since 1996, AOP extensions have been developed for multiple languages, including C++, Ruby, PHP, SAP ABAP and even COBOL. What Is AOP? At its core, AOP is the practice of encapsulating functionality common among multiple code elements yet independent of the Listing 1. A simple error-handling aspect. business logic, and applying that common functionality to the Module Module1 target source code elements declaratively. Sub Main() Try The common functionality is referred to as a crosscutting Call CreateError() concern because it “cuts across” the entire application as a Trace.WriteLine("OnExceptionAspect_Demo: Returned from CreateError") capability that’s useful, independent of the business logic. Catch ex As Exception Trace.WriteLine("") Common examples include error handling, logging, tracing, Trace.WriteLine("An Application Error Ocurred. " & ex.Message) instrumentation, transaction handling, security, caching, data End Try binding, undo/redo and even multithreading. None of these 10 End Sub examples involves business logic, but they’re all common and often necessary capabilities in any high-quality application. Sub CreateError() Dim zero As Integer = 0 Benefi ts of AOP Dim DivByZero As Integer = 10 / zero Trace.WriteLine("Numerator Divided by Zero:", DivByZero.ToString) The code that implements one of these crosscutting concerns is End Sub known as an “aspect,” and thus gives rise to the term “aspect-oriented programming.” What benefit does it provide the developer if the Public Class ExceptionWrapper functionality for these aspects can be removed from the primary Inherits PostSharp.Aspects.OnExceptionAspect source code and declaratively applied as needed to the application? Public Overrides Sub OnException( _ I’m truly excited by the benefits of AOP: args As PostSharp.Aspects.MethodExecutionArgs) Dim ErrorID = Guid.NewGuid ■ The business logic source code is much easier to read and Dim TraceMsg1 = String.Format("PostSharp: Error ID = {0}", ErrorID) understand, without the clutter of the code needed to support Dim TraceMsg2 = String.Format( _ crosscutting concerns. "PostSharp: {0} had an error at {1} of type {2}", args.Method.Name, DateTime.Now, args.Exception) ■ Less repetition in the code of the business logic means Trace.WriteLine("PostSharp Detected An Application Error") shorter developer times, fewer defects and a less-tedious Trace.WriteLine(TraceMsg1) coding experience. Trace.WriteLine(TraceMsg2) ■ Developers can better focus on implementing the proper Trace.WriteLine("") business logic. Dim ExceptionMsg = String.Format( _ "Please contact support with Error ID: {0}", ErrorID) ■ Less-experienced developers won’t have to learn to weave Throw New Exception(ExceptionMsg, innerException:=args.Exception) these crosscutting concerns throughout their code, and End Sub experienced developers will appreciate more fluid coding by End Class End Module

focusing primarily on business logic. ETTER RYAN BY ILLUSTRATION

34 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com | WPF | ASP.NET | ACTIVEX WORD PROCESSING COMPONENTS

Integrate professional rich text editing Rich Text Editing into your .NET based applications.

3')5HÁRZ2SHQ3')'RFXPHQWV Free Load, view, modify and convert Adobe PDF documents and reuse formatted text. License Search and analyze documents such as invoices or delivery notes. Spell Checking 5HSRUWLQJ5HGHÀQHG Add the fastest spell checking engine Build MS Word compatible mail Download to your Windows Forms, WPF or ASP. merge applications with our 100% free NET applications. 0DVWHU'HWDLOYLHZV Express version.

Word Processing Components US +1 877 - 462 - 4772 (toll-free) for Windows Forms, WPF & ASP.NET WWW.TEXTCONTROL.COM EU +49 421 - 4270671 - 0

Untitled-1 1 8/9/12 12:03 PM

{ ON VB }

Visual Studio 2012 and earlier versions do not directly support AOP. The aspect-like capability to declaratively apply custom code to methods can be found in Windows Communication Foundation (WCF) declarative filters and ASP.NET MVC dynamic filters.

The Path to AOP In order to fully implement AOP in a .NET application, you want the ability to move crosscutting concerns into separate aspects, apply them declaratively to one or more source code locations and—without changing the application architecture—enable the use of aspects. While the source code modified by the aspects may be aware of the aspects by leaving certain tasks to them, the source code should be ignorant of the internal implementation of the aspects. One way to add aspects into an application is to wrap each class with a dynamic proxy (outer shell) to provide additional functionality around the class, but the benefits of this approach are limited. Most dependency-injection frameworks in .NET provide some support for proxy-based AOP, which can be useful for logging, instrumen- tation and caching. This approach is only able to inject behaviors into the communication between a service and its consumer— not inside the service itself—so it can have the disadvantage of altering the application architecture to support aspects. Another way to add aspects to an application is through code generation, but this, too, is limited. This approach allows for more powerful code transformation, but requires recompilation of the application each time any of the aspects change. A third way to add aspects is through metadata-driven programming, utilizing dynamic languages such as IronPython or IronRuby. This can allow additional functionality to be added at runtime via aspects, but the complexity of implementing your own AOP framework is prohibitive. To see how to implement AOP in .NET using a full-featured AOP framework, I looked at PostSharp, which claims to be the most comprehensive aspect-oriented software available for .NET.

Introducing PostSharp PostSharp is available from SharpCrafters s.r.o. (SharpCrafters.com). A free Starter Edition providing the most commonly used aspect types is available, and supports commercial applications with a royalty-free runtime. The Starter Edition can be downloaded from the SharpCrafters site. Installation via the PostSharp NuGet package is recommended for those interested in the Pro version. All editions of Visual Studio 2010 are supported. PostSharp Pro extends the Starter Edition by adding the ability to implement more complex aspect scenarios, plus enhancements to the Visual Studio 2010 IDE with an Aspect Browser window and visual indicators in the code editor. PostSharp is installed into the folder C:\Program Files\PostSharp 2.1 on 32-bit Windows. PostSharp began as an open source project by Gael Fraiteur in 2004, with the first stable release in 2007. As PostSharp grew in popularity, Fraiteur founded SharpCrafters in 2009 to allow him to devote his efforts to PostSharp full-time. The commercial launch of

The complexity of implementing your own AOP framework is prohibitive. { ON VB }

PostSharp Pro came in March 2010. SharpCrafters is headquartered The aspect ExceptionWrapper generates a series of technical in Prague, Czech Republic. messages identified by a GUID to the Debug output window when an exception occurs. This simulates what would be logged when How Does PostSharp Work? an exception occurs. It then throws a new exception with a Once PostSharp is installed, you encapsulate the desired crosscutting user-friendly message to contact support for this Error ID. The functionality into an aspect method and then apply that aspect original exception is carried as the innerException so that the individually to the desired classes or methods within the calling routine retains full flexibility in how to handle the application, either declaratively using attributes, or to a exception. The code in Listing 1 plus a reference to the PostSharp namespace using a multicast attribute. assembly was all that was needed to create this example in Visual PostSharp uses a post-compilation approach by modifying the Studio 2010 after PostSharp was installed. Microsoft Intermediate Language (MSIL) to include the aspect behaviors. This makes PostSharp .NET language-independent, as all .NET languages ultimately produce MSIL output. MSIL is extensively documented in the ECMA-335 standard specification. MSIL transformation is also used by Microsoft in code contracts and is fully supported. Aspects must be marked Serializable, because the aspect code is serialized and added to the .NET assembly as a managed resource so it can be available at runtime. PostSharp is build server friendly. As part of the build process, PostSharp can and should be integrated with the build server process; if PostSharp is deployed to the source code repository, it doesn’t need to be installed on the build server. If installed on the build server, PostSharp has a minimal UI, which can be suppressed with registry settings. PostSharp doesn’t require a separate license for the build server. PostSharp supports code obfuscation to discourage reverse engineering the source code (see SharpCrafters.com for the current list of supported obfuscator products).

Coding an Exception Handler Aspect in Visual Basic The aspect base class OnExceptionAspect is one of the commonly used aspects, and is available in the free PostSharp Starter Edition. This aspect wraps around the target method with a try-catch construct and provides the OnEntry, OnSuccess, OnException and OnExit advices. An advice is anything that adds a behavior or structural element to source code. In this case, an advice can be thought of as one of the overrideable methods in a PostSharp aspect. Listing 1 (p. 34) shows a console application implementation of the aspect OnExceptionAspect. It provides the useful behavior of logging technical details of an exception for later investigation, while preventing potentially undesirable technical details, such as a connection string or resource path, from being shown to the user.

{ ON VB }

and adds the desired behavior. The MethodExecutionArgs parameter provides the needed information about the exception that was thrown. Figure 1 shows the output of the example. The trace messages in the first four lines Figure 1. Output of the ExceptionWrapper aspect. were written by PostSharp because an error occurred in a Looking at Listing 1, the aspect is applied to the CreateError method decorated by the ExceptionWrapper attribute. The last line method using an attribute. No error-handling code is present shows the suggested non-technical error message shown to the user. within the method, yet it receives the full benefit of the custom What if the ExceptionAspect should handle only certain error-handling logic in the ExecutionWrapper aspect. Coding the exception types for a particular target? How are these exception aspect involves creating a serializable class that inherits from the types specified, and how does the aspect respond to only those desired base class aspect, OnExceptionAspect. exception types? Listing 2 shows how the GetExceptionType The base class provides a series of methods that do nothing method can be overridden in the ExceptionWrapper class to filter until overridden. In order to write trace messages in the case of an the exception types for the aspect. The commented attributes exception, ExceptionWrapper overrides the OnException advice show the various ways the attribute can decorate the target Programming

Aspect-Oriented Aspect-Oriented method with parameters, for either a single exception type or multiple exception types. If the GetExceptionType method returns Listing 2. Handling selected exceptions in the aspect. an exception type matching the current exception during ' application execution, then it’s handled; otherwise, it’s ignored. ' ' Multicast ' The PostSharp Starter Edition supports OnMethodBoundaryAspect. It’s invoked each time the method is called, and it, too, supports Public Property HandleExceptionTypeArray As Type() the OnEntry, OnSuccess, OnException and OnExit advices. This Public Property HandleExceptionSingleType As Type aspect is appropriate for implementing tracing or execution Public Overrides Function GetExceptionType( _ instrumentation by tracking entry and exit of the desired target targetMethod As System.Reflection.MethodBase) As System.Type methods or classes. Dim result As Type = Nothing Decorating each method with an attribute isn’t practical for the Dim MethodExceptionType = MyBase.GetExceptionType(targetMethod) large number of target methods that might be involved in tracing 'If no explict exception types specified, handle any type of exception or instrumentation. For this you need the PostSharp multicasting If IsNothing(HandleExceptionSingleType) AndAlso IsNothing( _ capability, which allows an aspect to be applied to multiple targets HandleExceptionTypeArray) Then result = MethodExceptionType by adding a directive to the AssemblyInfo.vb file. Multicast is how Else an aspect can be applied to an assembly without directly modifying 'If there is a named single exception type and it is a match, handle it the target source code. If IsNothing(HandleExceptionSingleType) = False AndAlso _ The first Assembly directive in the following code applies the HandleExceptionSingleType = MethodExceptionType Then result = MethodExceptionType TracingWrapper aspect to all classes and methods in the End If MyApp.BusinessLayer namespace, including constructors. If you wish to limit the aspect to only methods of a certain name, you 'If there is an array of exception types, and not already a match, 'handle the exception if any in the array are a match could use an Assembly directive similar to the second, which If IsNothing(HandleExceptionTypeArray) = False AndAlso limits the instrumentation to only those methods that contain IsNothing(result) = True Then “InsertRecord” in the method name: For Each testType In HandleExceptionTypeArray If testType = MethodExceptionType Then result = MethodExceptionType End If Next When attempting to multicast an aspect, be sure to test it as an End If End If attribute on a single method first, to ensure it works properly.

'Will be nothing only if types specified and no match Enhancing Role-Based Security Return result End Function Declarative role-based security is supported in standard .NET applications, such as restricting a method to members of a list of roles.

The PostSharp multicasting capability allows an aspect to be applied to multiple targets by adding a directive to the AssemblyInfo.vb file.

38 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com { ON VB }

Listing 3. A practical business scenario for advanced role-based security. Public Class UserSecurity Dim UserName = My.User.CurrentPrincipal.Identity.Name Public Shared Users As List(Of UserSecurityInfo) Dim UserSecuritySettings = _ Public Shared Sub PopulateUserSecurity() UserSecurity.Users.FirstOrDefault(Function(x) x.UserName = UserName) Users = New List(Of UserSecurityInfo) If IsNothing(UserSecuritySettings) = False Then Users.Add(New UserSecurityInfo With {.UserName = "Tom.Talker", _ 'Validate the user's business unit to the one passed in the method .BusinessUnit = "Sales"}) If args.Method.IsConstructor = False Then Users.Add(New UserSecurityInfo With {.UserName = "Allan.Accountant", _ Dim thisMethod As System.Reflection.MethodInfo = CType(args.Method, _ .BusinessUnit = "Accounting"}) System.Reflection.MethodInfo) End Sub Dim BUparam = End Class thisMethod.GetParameters().First(Function(x) x.Name = "BusinessUnit") If IsNothing(BUparam) = False Then Public Class UserSecurityInfo Dim BUparameter As String = args.Arguments.GetArgument(BUparam.Position) Public Property UserName As String If BUparameter <> UserSecuritySettings.BusinessUnit Then Public Property BusinessUnit As String Dim ErrorMsg = End Class "User: {0} is not authorized to requisition for business unit: {1}" Throw New Security.SecurityException( _ Public Class BusinessLayer String.Format(ErrorMsg, UserName, BUparameter)) End If Public Shared Sub CreateRequisiton(BusinessUnit As String) End If 'This method executes only if the current user has the specified business unit End If Return Else End Sub Throw New Security.SecurityException( _ End Class String.Format("User {0} Not Found in Users Security Table", UserName)) Programming Aspect-Oriented Aspect-Oriented End If End If Public Class AOPSecurity End Sub

Public Overrides Sub RuntimeInitialize(method As System.Reflection.MethodBase) Public Class ValidateBusinessUnitAttribute If IsNothing(UserSecurity.Users) Then Inherits PostSharp.Aspects.OnMethodBoundaryAspect UserSecurity.PopulateUserSecurity() Public Overrides Sub OnEntry(args As PostSharp.Aspects.MethodExecutionArgs) End If 'Get current running user End Sub If My.User.IsAuthenticated = False Then End Class Throw New Security.SecurityException("Unauthenticated User") End Class Else

What if the business requirement is to restrict the users to performing (including the Windows Runtime) and Visual Studio 2012 will be functions for only their own business unit? Let’s use the PostSharp supported in PostSharp 3.0, which is currently under development. Starter Edition to create a realistic purchasing scenario where PostSharp can be used with Silverlight, the .NET Compact employees can only requisition items for their own business unit. Framework and Windows Phone. Separate reference assemblies Listing 3 demonstrates how to use the OnMethodBoundaryAspect are provided for these environments. PostSharp 3.0 will use the to validate that only authenticated users can execute the method, and Portable Class Library so that a common codebase can be used to only authenticate users whose UserSecurityInfo.BusinessUnit across the .NET platforms. property matches the BusinessUnit parameter passed into the method. The assumption is that the application will prompt A New Aspect to Your Coding for the desired business unit before displaying the purchasing I hope this article has helped you understand what AOP is and how requisition form, and pass that in as a parameter to the it can simplify your coding experience without sacrificing desired CreateRequisition method. functionality. I only scratched the surface of what can be done Listing 3 overrides the OnEntry advice to determine if the user is with AOP as implemented by PostSharp. I plan to incorporate authorized for that business unit. It demonstrates the ability to AOP as a routine part of my coding efforts so that I can focus more view the parameter values of the target method for use in the on business logic and less on routine repetitive code, and gain aspect’s decision logic. The BusinessUnit parameter can appear some significant time savings. Maybe I’ll even gain enough time anywhere in the target method parameter list, but must be called for a vacation away from my computer! VSM exactly “BusinessUnit.” By overriding the RuntimeInitialize method, the aspect ensures that the user security table has been Joe Kunk is a Microsoft MVP in Visual Basic, three-time president of the initialized prior to its use. The aspect doesn’t check security if the Greater Lansing User Group for .NET, and developer for Dart Container target method is the constructor. Corp. of Mason, Mich. He’s been developing software for almost 30 years and As you can see, some rather advanced security was applied to a has worked in the consulting, education, government, financial and method simply by decorating it with the ValidateBusinessUnit attribute. manufacturing industries. Kunk coauthored the book “Professional DevExpress ASP.NET Controls” (Wrox to Programmer, 2009). Compatibility and Platforms He can be reached via e-mail at [email protected]. PostSharp is compatible with Visual Studio 2008 and Visual Studio 2010. The IDE enhancements are available only with the Pro version, GO ONLINE and are not compatible with the Express version, as it doesn’t support Go to VisualStudioMagazine.com/Kunk0912 to read this article online any IDE extensions. SharpCrafters has confirmed that Windows 8 and to download the sample code.

VisualStudioMagazine.com · September 2012 · VISUAL STUDIO MAGAZINE 39

{ UI CODE EXPERT }

WPF Programming L isting 1. Implementing INotifyPropertyChanged with C# 5.0 for a property. Two new features of C# 5.0 can signifi cantly improve your public class MainWindowViewModel : INotifyPropertyChanged Windows Presentation Foundation UI programming. { string _PiValue ; BY MARK MICHAELIS public string PiValue { get { return _PiValue; } Unlike previous releases, C# 5.0 comes with set just a couple new features: CallerInfo attributes { _PiValue = value; and the Task-based Asynchronous Pattern PropertyChanged( (TAP). However, these changes are particularly this, new PropertyChangedEventArgs("PiValue")); significant and relevant to Windows UI } }

C# 5.0 Features C# 5.0 programming. In this article I’ll delve into public event PropertyChangedEventHandler PropertyChanged the details of how Windows Presentation = delegate { }; Foundation (WPF) programming is improved by these additions. By way of demonstration, I’ll methodically improve a small // ... } WPF Model-View-ViewModel (MVVM) application that initially doesn’t have the benefit of any new language features. In this program I’ll calculate the value of pi to n characters. The This is partly due to the fact that I overload the PropertyChanged UI for the application is quite simple, as pictured in Figure 1 (p. 42). method to no longer require the sender, defaulting it instead to The application calculates the value of pi out to the number of this. More important is that I no longer pass in the property name, digits specified in the text box—a deliberately high-latency task but instead rely on the complier to determine it for me. The that would block the UI if I didn’t offload it to a Task (the semantic compiler knows to do this because of the CallerMemberName equivalent of a thread). I call the application ApplePi. attribute. When the compiler encounters this attribute and determines that the caller isn’t specifying the corresponding CallerFileInfo, CallerMemberInfo, CallerLineInfo Attributes argument value, it automatically injects the caller’s member name. The first programming problem is the fact that an MVVM application In other words, in spite of the fact that Listing 2 doesn’t specify needs to raise PropertyChanged events on any ViewModel property any arguments in the PropertyChanged statement, the memberName that changes. This is necessary because a ViewModel implements value is “PiValue” and not “.” Note that the CallerInfo the System.ComponentModel.INotifyPropertyChanged interface attributes (of which there are a total of three) do require that the in order to support the binding of properties from the View to the parameter be assigned a default value, even though the value will ViewModel. In doing so, any changes in the ViewModel will never be used. In other words, even though a default value of automatically be reflected in the View, and vice versa. Listing 1 “” appears, the purpose is only to make the memberName provides a basic implementation of the interface for a property attribute optional, not to provide a default for the parameter. In with the name PiValue. fact, the default value of “” will never be used except in a One of the unfortunate characteristics of INotifyProperty- corner case, such as when it’s called from an earlier version of C#. Changed.PropertyChanged events is that they take a string There are a number of additional nonessential changes in corresponding to the property name. The problem with a string is Listing 2 that deserve mention—all of them orthogonal to the there’s no compile-time checking to verify that it’s spelled correctly. CallerMemberName decorated parameter. First, PropertyChanged An incorrect spelling will actually break the binding, so changes in is overloaded three times, each time eliminating the need to pass the ViewModel won’t be reflected in the UI. another argument. Second, the line: The solution with C# 5.0 (there’s also a lambda expression private void PropertyChanged(object sender, solution) to passing the property name without any compile-time PropertyChangedEventArgs eventArgs, validation is to not pass the property name explicitly, but instead [CallerMemberName] string memberName = "") to rely on the Microsoft .NET Framework 4.5 CallerMemberName has parameters for both the PropertyChangedEventArgs. In these, the parameter attribute (known as the CallerMemberNameAttribute), PropertyName value is already set, and the memberName parameter as shown in Listing 2 (p. 42). is defaulted using the CallerMemberName attribute. By allowing There’s a lot more code in Listing 2 than there was in Listing 1, but both, I’m able to check that the eventArgs argument is initialized only the lines of actual significance are highlighted. Notice how correctly (with correct spelling) even if the call site never changed raising the PropertyChanged event has gone from: to call the simpler PropertyChanged (with no arguments) method. PropertyChanged( this, new PropertyChangedEventArgs("PiValue")) One last thing to note is that C# doesn’t support overloading on to simply: members also declared as an event. For this reason, I’ve changed PropertyChanged the event declaration from an implicit INotifyPropertyChanged ETTER RYAN BY ILLUSTRATION

40 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Raising the Bar… And Pie, and Spline and Scatter… on Mobile Business Intelligence

Compatible with Microsoft® Visual Visualize your BI in 50+ ways, and on just as Studio® 2012 many devices. From candlesticks to polar and radial charts, nobody offers the breadth and depth of dynamic, high fidelity, totally mobile charting solutions that you get from Infragistics’ NetAdvantage. Try a free, fully supported trial of NetAdvantage for .NET today! www.infragistics.com/NET

Infragistics Sales US 800 231 8588 • Europe +44 (0) 800 298 9055 • India +91 80 4151 8042 • APAC (+61) 3 9982 4545 Copyright 1996-2012 Infragistics, Inc. All rights reserved. Infragistics and NetAdvantage are registered trademarks of Infragistics, Inc. The Infragistics logo is a trademark of Infragistics, Inc. All other trademarks or registered trademarks are the respective property of their owners.

Untitled-5 1 7/10/12 3:59 PM

{ UI CODE EXPERT }

any exceptions were to escape from the asynchronous task execution, they’d need to be caught as AggregateExceptions, not the native-exception type originally thrown.

The ExceptionDispatchInfo Class There’s an important new capability added to the .NET Framework 4.5 that has special relevance to the AggregateException. The AggregateException is a collection of all the exceptions thrown by asynchronous or parallel-related execution. After catching an exception, therefore, I have to iterate through the InnerExceptions property and appropriately handle each of these source exceptions. Unfortunately, catching an AggregateException prevents simply calling throw to re-throw the actual exception when no appropriate Figure 1. A simple ApplePi MVVM application UI. handler is available, because the exception was already caught and wrapped in an AggregateException. The result is to re-throw the inner implementation to an explicit implementation. More important exception explicitly and, in doing so, lose the stack trace entirely. than addressing the name collision, switching the interface In the .NET Framework 4.5, however, there’s a new class, implementation to an explicit implementation makes it less readily ExceptionDispatchInfo, that can be instantiated to re-throw the available for invocation because a cast will be required. That way, exception while not resetting the stack trace. Use Exception-

C# 5.0 Features C# 5.0 whether leaving caller invocations as they were (instantiating DispatchInfo.Capture(exception).Throw where “exception” is the PropertyChangeEventArgs or not), the intercepting methods will instance you’re trying to re-throw. still be called—an important characteristic when it comes to Another important factor that must be addressed relates to the dispatching calls into the UI thread. UI invocation from the continuation tasks that are almost An equally critical location to leverage the CallerInfo attributes is when writing trace files. Consider the TraceWriteLine method Listing 2 . Implementing INotifyPropertyChanged using shown in Listing 3 (p. 44). CallerMemberNameAttribute. Like the PropertyChanged method, TraceWriteLine decorates public class MainWindowViewModel : INotifyPropertyChanged its parameters with CallerInfo attributes to log the message detail { information about the trace event without needing to pass in any string _PiValue; arguments on each invocation. This is especially useful in the case public string PiValue of a trace message, because—barring hardcoding the value at the { get { return _PiValue; } call site—it’s necessary to iterate over the stack to determine the set name. Not only is such logic nontrivial, but it introduces a { significant performance hit. In contrast, with CallerInfo attributes, _PiValue = value; PropertyChanged(); both the code and runtime performance hits are avoided entirely. } } Task-Based Asynchronous Pattern private void PropertyChanged( The most significant enhancement to C# 5.0 is the Task-based [CallerMemberName] string memberName = "" ) Asynchronous Pattern (TAP). TAP is built on top of the .NET { Framework 4 Task Parallel Library (TPL), a significantly better PropertyChanged(this, memberName); } abstraction on top of the System.Threading API from earlier .NET Framework versions. However, there are still some drawbacks to private void PropertyChanged(object sender, TPL. Most notable is that the code flow has to get turned “inside [CallerMemberName] string memberName = "") { out” as delegates are set up, task continuations are established and PropertyChanged(sender, exception handling gets integrated. To illustrate this, consider the new PropertyChangedEventArgs(memberName), OnStartCommand method invoked when a user clicks Start on memberName); } the ApplePi application (see Listing 4, p. 44). private void PropertyChanged(object sender, Semantically, the code is simply calling the PiCalculator.Calculate PropertyChangedEventArgs eventArgs, and sequentially retrieving the next segment of digits that are [CallerMemberName] string memberName = "") { calculated. Listing 5 (p. 44) shows the equivalent synchronous logic Trace.Assert( without the deeply integrated TPL code of Listing 4. eventArgs.PropertyName == memberName) Obviously, the readability is significantly hampered when _PropertyChanged(sender, eventArgs); converting the code to be asynchronous. Unfortunately, Listing 4 is } PropertyChangedEventHandler _PropertyChanged = delegate { }; still missing significant portions of critical functionality. For event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged example, what if I wanted to catch an exception issued from { PiCalculator.Calculate? In Listing 5, I can just surround the body of add { _PropertyChanged += value; } remove { _PropertyChanged -= value; } the OnStartCommand method with a try-catch block. } This isn’t the case for Listing 4. At the very least, I’d need to separately wrap the body of each delegate in a try-catch block—a // ... } duplicate copy of the same try-catch block in each. Furthermore, if

42 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com MetroTactual [me-troh tak-choo-uhl]

Compatible with Microsoft® Visual Studio® 2012

noun, adjective 1. Modern, clean, sleek, stylish, touch- friendly design and UX 2. Feng Shui for your apps 3. Available in NetAdvantage 12.1 toolsets See also: NetAdvantage for .NET

Try your free, fully supported trial today. www.infragistics.com/NET

Infragistics Sales US 800 231 8588 • Europe +44 (0) 800 298 9055 • India +91 80 4151 8042 • APAC (+61) 3 9982 4545 Copyright 1996-2012 Infragistics, Inc. All rights reserved. Infragistics and NetAdvantage are registered trademarks of Infragistics, Inc. The Infragistics logo is a trademark of Infragistics, Inc. All other trademarks or registered trademarks are the respective property of their owners.

Untitled-5 1 7/10/12 4:00 PM

{ UI CODE EXPERT }

The problem with the code in Listing 4 is that each time it updates Listing 3 . Leveraging CallerInfo attributes on a a property such as PiValue, it triggers the INotifyProperty- diagnostic/trace method. Changed.PropertyChanged that, through binding in the XAML, private static void TraceWriteLine( directly calls into the UI. And because Windows is a single-threaded string text = default(string), UI implemented on a message pump architecture for dispatching [CallerFilePath] string fileName = default(string), UI-related work, all threads other than the UI thread shouldn’t [CallerMemberName] string methodName = default(string), [CallerLineNumber] int lineNumber = default(int)) directly interact with UI controls and windows of any kind. { To address the UI synchronization issue, contexts need to be string message = string.Format( switched before any and all property changes (assignments to "{0}({1}): {2}- ThreadId[{3}]:", fileName, lineNumber, methodName, IsStartEnabled or PiValue), or else the synchronization code needs System.Threading.Thread.CurrentThread.ManagedThreadId, to be injected into the PropertyChanged methods. Because all text); INotifyPropertyChanged.PropertyChanged invocations have been // ... } concentrated into to a single method, it makes sense to place them there. That’s what Listing 6 (p. 46) shows. The keys to the UIAction class are, first, the check with certainly executing in a different “synchronization context” (a System.Windows.Application.Current about whether dispatching to crude equivalent of thread in this case). The TPL consults the the UI thread is required; and second, if UI dispatching is determined synchronization context in order to schedule continuation tasks to be necessary, the System.Windows.Application.Current.Dis- and ContinueWith delegates, which are both efficient and safe. patcher.Invoke(target) call takes care of it. It’s noteworthy that although

C# 5.0 Features C# 5.0 It’s efficient because the synchronization context is consulted by there are both synchronous and asynchronous versions of the Invoke the task scheduler to determine activities, such as when to create a method available, UIAction uses the former to catch any exceptions new thread rather than reuse old ones, or dispose of a thread. It’s that may occur and move them back to the calling invocations safe because it’s the synchronization context that tracks whether it’s context, rather than letting them escape as unhandled exceptions. safe to continue executing on the same thread as before, or whether If we consider the simplicity of the ApplePi application—calculate to dispatch work to a different thread, such as the UI thread. the value of pi and display the calculation in flight (as it becomes available)—there’s an awful lot of plumbing required. It’s this plumbing that TAP sets out to address (see Listing 7, p. 46). Listing 4 . Dispatching high-latency work to a different task. Notice how remarkably similar Listing 7 is to Listing 5. In fact, the public class MainWindowViewModel : INotifyPropertyChanged two listings are identical except for the contextual keyword { additions of async and await. Yet don’t miss the volume of public Task OnStartCommand() complexity that they eliminate. { There are a few misconceptions about async that I want to address: IsStartEnabled = false; ■ Misconception No. 1: A method decorated with the async PiValue = string.Empty; keyword is automatically executed on a worker thread when Task calculateTask = called. This is absolutely not true. The method is executed Task.Run( () => PiCalculator.Calculate(SegmentSize, 0)); normally, on the calling thread. An async method starts some asynchronous work represented by a Task and then (if it isn’t Task continuationTask = void) returns the Task to its caller. That object might calculateTask.ContinueWith(antecedent => represent an operation being performed on another thread, or, { PiValue += antecedent.Result; in some cases, it might represent an operation performed on }); the current thread in the future. Regardless, there’s nothing unusual about a call to an async method from the caller’s for (int i = SegmentSize; i < Digits; i+=SegmentSize) { int currentDigit = i; continuationTask = Listing 5 . The semantic equivalent OnStartCommand continuationTask.ContinueWith(antecedent => implementation without TPL. { public void OnStartCommand() int nextSegmentSize = { Math.Min(SegmentSize, IsStartEnabled = false; Digits - PiValue.Length +2); string nextSegment = PiValue = string.Empty; PiCalculator.Calculate( for (int i = SegmentSize; i < Digits; i+=SegmentSize) nextSegmentSize, currentDigit); { PiValue += nextSegment; int nextSegmentSize = }); Math.Min(SegmentSize, } Digits - PiValue.Length +2); continuationTask = continuationTask.ContinueWith(antecedent => string nextSegment = { PiCalculator.Calculate( IsStartEnabled = true; nextSegmentSize, i); }); PiValue += nextSegment; return continuationTask; } } // ... IsStartEnabled = true; } }

44 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Just the Right Touch Get in touch with the new NetAdvantage for .NET 2012 V. 1 today, with a free, fully supported trial! www.infragistics.com/NET

Compatible with Microsoft® Visual Studio® 2012

Infragistics Sales US 800 231 8588 • Europe +44 (0) 800 298 9055 • India +91 80 4151 8042 • APAC (+61) 3 9982 4545 Copyright 1996-2012 Infragistics, Inc. All rights reserved. Infragistics and NetAdvantage are registered trademarks of Infragistics, Inc. The Infragistics logo is a trademark of Infragistics, Inc. All other trademarks or registered trademarks are the respective property of their owners.

Untitled-5 1 7/10/12 4:00 PM

{ UI CODE EXPERT }

Listing 6. Dispatching work to the UI thread. Listing 7 . Task-based Asynchronous Pattern with async and public class MainWindowViewModel : INotifyPropertyChanged await contextual keywords. { public async Task OnStartCommand() // ... { IsStartEnabled = false; private void PropertyChanged(object sender, PropertyChangedEventArgs eventArgs, PiValue = string.Empty; [CallerMemberName] string memberName = "") for (int i = 0; i < Digits; i+=SegmentSize) { { Trace.Assert( int currentDigit = i; eventArgs.PropertyName == memberName); int nextSegmentSize = UIAction.Invoke(() => Math.Min(SegmentSize, { Digits - PiValue.Length +2); _PropertyChanged(sender, string nextSegment = eventArgs); await Task.Run(() => PiCalculator.Calculate( }); nextSegmentSize, i)); } PiValue += nextSegment; // ... }; } IsStartEnabled = true; public static class UIAction } { public static void Invoke(

C# 5.0 Features C# 5.0 Action action, T parameter) without using await. The await keyword evaluates the { expression that follows it (usually of type Task or Task), Invoke(() => action(parameter)); adds a continuation to the resulting task and then immediately } public static void Invoke(Action action) returns control to the caller. The creation of the task has started { asynchronous work. The await keyword means the developer DispatcherObject dispatcher = wants the method caller to continue executing its work on this System.Windows.Application.Current; if (dispatcher == null thread while the asynchronous work is processed. At some || dispatcher.CheckAccess() point after that asynchronous work is complete, execution will || dispatcher.Dispatcher == null resume at the point of control following the await expression. ) { The async keyword makes it clear that the method that follows will action(); be automatically rewritten by the compiler. It also informs the compiler } that usages of the await contextual keyword in the method are to be else treated as asynchronous control flow, and not as ordinary identifiers. { SafeInvoke(action); In this example, I purposely chose to call a CPU-intensive } method—CalculatePi—that wasn’t built as an asynchronous } method. However, the .NET Framework 4.5 comes with a suite of

// We want to catch all exceptions here API enhancements that make using TAP easier. In the .NET // so we can rethrow Framework 4.5, every high-latency operation includes an *Async private static void SafeInvoke(Action action) equivalent that also returns a Task/Task. { The significance is that asynchronously invoking a high-latency Exception exceptionThrown = null; Action target = () => method while having it appear in a synchronous set of steps { requires nothing more than prefixing the calling method signature try with the async modifier and then prefixing the *Async method { action(); invocation with await. That’s it! With these methods, it isn’t even } necessary to use Task.Run or Task.Factory.StartNew. catch (Exception exception) { exceptionThrown = exception; More-Effi cient Web Sites } TAP is just as relevant to the server as it is to the Windows client. }; Previously, threads were consumed waiting for high-latency calls System.Windows.Application.Current.Dispatcher.Invoke(target); to return, even though those threads weren’t heavily engaged with if (exceptionThrown != null) { any CPU-related work. Now, with TAP in place for both the rich throw exceptionThrown; client application and the Web stack, Web site efficiency can be } radically improved because those same threads that were } previously waiting for high-latency operations can now be dispatched to process additional Web requests, thereby perspective. It’s a method typed as returning a task, it’s called significantly increasing the load capacity of a Web site. VSM normally and returns an object of its return type normally. ■ Misconception No. 2: The await keyword causes the current Mark Michaelis started IntelliTect and serves as chief technical architect and thread to block until the awaited task is completed. This is trainer. Since 1996, he’s been a Microsoft MVP for C#, Visual Studio Team also absolutely not true. If you want the current thread to System and the Windows SDK. In 2007, he was recognized as a Microsoft block until the task completes, call the Wait method on a Task regional director. You can visit his blog at intellitect.com/mark.

46 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com emement1);ent1); a areaSeriesreaSerieies.A Add(seriesElement2);Add(se(s rriesElement2t2);) areaSeriesareaSeries.Ad Add(seriesElement3);A d(seriesElement3); //// AddAdd seriesseries to the plot areaarea plotAreaplotArea.S Serieseries.Ad Add(areaSeries);d(areaSeries); //page//page.El Elementsemenem ts.A Add(dd(d newne LayoutGrid()LaLayyoutGrid() ); /// AddAdd thethe pagepage elementselements to the page AddEAAddEA s, 240, 0); AddEAN1AN 3SupSup5(pa5(p ge.Elemeentnts, 480, 0); AdddUPCVersionA(page.Elemene ts, 0, 135); AddUPCVersionASup2(page.Elements, 240, 135); AdddUPCd CVerssionAo Sup5((page.Elemennts,t 480, 135); AddEAN8(page.Elements, 0, .Elements, 480, 270);; AddddUUPCVersionE(papage.Elementts, 0, 405); AddUPCVersionESuE p2(page.Elements, 240, 405); AddUPCVersionESup5(pageage.Elelemments, 48800, 4405); // AAdd the page tot the document document.Pages.Add(pa CaptionAndRectanga lee(elemeements, “EAN/JA/JAN 13 Bar Codde”, x, y, 204, 99); BarCode barCode = new Ean13(“123456789012”, x, y + 21); barCode.XX+ +=+ ((2004 - baarCoode.GettSymbolWidth()h ) / 2; elements.Add(barCode); } private vo dRectangle(elemente s,, “EANEAN/JAN 13 Bar Code, 2 digit supplement”, x, y, 204, 99); BarCode barCode = new Ean13Sup2(“12 234556789678 0121212”, x, y + 211); barCoode.X += (204 - barCode.GetSymbolWidth()) / 2; elements.Add((barC ts, float x, float y)y { AddCaCaptionAndRectanangle(elements, “EAN/JAN 13 Bar Code, 5 digit supplement”, x, y, 204, 99); ( g[ ] g) BaB rrCode barrCode = new Ean13SupS 5(“12345678901212345”, x, y + 21); ba s.Add(barCode); } pprivatete vooid AddUPCVPCVersiers onA(Group elements, float x, float y) {Add{ CaptionAndRectangle(elements,{ “UPC Versionio A Baar CCoode”, x, y, 204, 99);; BarCoode barCode = new UpcVersionA(“12345678901”, xx, y + s.Add(barCode); } pprivatete vooid AddUPCVPCVersiers onASup2(Group elements, float x, floato y) { AddCaptionAndRectangle(elementm p ““UPCC Version E Bar Code, 2 digit supplement”, x, y, 204,4 99); BarCoodeod 21) ; barCode.X += (2( 04 - babarCode.GeetSymbymbolWidth()) / 2; elements.Add(barCode);e } private void AddUPCVVersionASSuup5( g g ( p p ) Group elements,n float x, flfloaflo t digit supplement”,t” xx, y, 2004, 99); BarCode bbarCode = new UpcVep rsionASuAS p5(“12343 567890112345”, x, y + 21); barCarCode.Xde.X [ ] += (204 - barCode.GetSymbom olWidth()) / 22; ele t x, float y) { AddCaptionnAndRAnd ectangle(eleelemments, “EAN/JANN 8 Bar Code”, x,x y, 204,0 99); BarCode barCode = new Ean8(n8 “1 [ ] 2345670”, x, y + 21); OpenFileileDiala og fileDie aloloog = g.Filter = “Adobeob PDPDF filees (*.pdf)|*.pdf|Alll Files (*.*)|*.*”; if (fileDieD alog.SShowDiialog() == DialogResult.OK) { pdfVf ieweewer.OpOpen p y y yyp (fifileDialog.FilleName, “”); } SaveveFileDialog saveFileileDDialoog = neneww Sav Dialog.Filter = “AdoAdobe PDF files (*.pdff)|*.pdpdf|A|All Files (*.*)|*.*”;”; iff (saveFFileDialolog.Showh Dialog() ==DialoalogResRee ult..OK) { pdfVView High h SecuSec rity sec urit y new w High h Secu u rity y (“O Ow nerP assw ord” , “U“ serPassw ord” ) .SSaveAsve (saveFieFileDia printer = pdfViewer.Per rinterr; prip nter.PriintWiW thDialog(); } elsee { MesssageBox.SShoww(“Please open a fifile to printrin ”)”); }OpenFin le y ppy DDialoog fileDieD alog = new OpenFileDDialog(); fileDiaDialog.og Tittle = “Opepen Filel D les (*.*)|*.*|Addobee PDF fileses (*.p*.pdf)|*.pddf”; ifi (fifileDialog.ShowwDialalog() === DialogResult.ult OK) { DynamicPDFViewewerClass testees = y y neew DynammiccPDFViewerClass((); PPDFPrinter pprintererr = tet st.OpenFFileFo = File.ReadAAllBytes(@”C:\M:\MyDyDoc.pdff”); //u// sing System.Runntimme.IntntteropServicces;GCHandled gch=GCH= CHaananddle.Aloc(conteents, p GCHandleTTypee.Pinnedd);) IIntntPtr coconton entsIntPtr = g tents.Lengthh, “”); AddCaCaptioonAndReectanglan ee(pageElementts, “BBBookkmark Pagee Elemeent:”, x, y);; pagpaa eEeEleemeents.Add(newtesw t ( p p ) Bookmaark(“Bookmarked Textt”, x + 5, y ++2 20, pparentre OutlO ine));) pa 215, 10, Fonnt.TTimemesRomanma , 10)); } prriivate vooid AddCiircle(GGroup paageElemeennts,nts float x,x floafloatyt y) { //Add/A s a circlt to the papageg p ( p p ) Eleemenmentenents AddCapCa tiont AndRdRectae Add(new Cirrcle(x + 112.5f5f, y + 50f, 1007.5f, 300f, RgbColoolor.RRRed, RgbbColor.Bluee, 2, LineL eStyylyle.Dae DashLas L rge))); } pprivate void AdA d p () FormatteeddTexxtAreea(Groupp paageElements, flfloaat x, flfloat y) { // Adds a formatted textte a micPDFPDF/b>&tm; GGenerator v66.0 for ..NETNET has a forrmattted tetext t arrea paage “ + “eleemment. This prroviddes rich fororm } atting suppupport for texext that appap eears in the doocumment. You have “ + “completlete cocontrolol ovever 8 paragraph left indentattionn, righht indenentation, aligliggnnment, allollowing orphaan linnes, aand white “ + “spaace prereservata ion; 6 foont propropeerties:e s’>font facece, font “ + “size, c 2 line propertieses: leading,g andd leaddinngg type. TText can also be rootateed.”;p> FFororo mattm edeedTeTeextArx ea formattedTTextAreArea = new FormattedTextTex Areare (formattat edHHtmll, x + 5, y + 20, 215, 60, FonttFammily.Helvetictica, 9, ffalalsse);se) // Sets the i ddCaptionAAndReRectanct gle(e(pageElemeennts, “Forrmattedtte TextT Areeae Page Element:”,, x, y);y)y AddCAdAddCaptionAnAndReectangnglele(pageElements, “Formatm tedTextAx rea OverOv flflow TText:”, x + 2279, y); pageElements.Add(foormarmattedTTextAxttAArea)r ; // CrCrer ate tArea overflowFormatrm tedTdTextAArea = formamattedt dTd extArea.GettOveerflowwwFormatmatteddTTexextAx rea(re x + 28284, y + 200); pageElements.Add(overflowFormattedTextAArea)); } pprivate vooid AddImage(Groupp pagpageElements, floatt x, float y)){ { /// Add ents, “Imagee Page Elementen :”, xx, y); Immage imaage = new Imaage(SServver.Mr.MapPatatth(“.“ ./I./Im./ ages/DPDDFLogL o..png”), x + 112.5f, y + 50f, 0.24f); // Image is ssizzed and centeredd inn the rectangle immage.age SetBoundunds(215,5 60);0) image.VAVAAlign ge); } privatte void AAddLabela (Groupp pageageElememments, float x, flfloat y) { //A/ Addss a llabel to tht e pap gegeElementts AddCaptionAndRectangle(pageElemenm ts, “LabLa el & PPageNummbeeringLabel Page EleE mments:”, x, y);y) striingg laabelTextxt = “Lab ain page numbumbering: %%CP%% of %%%TP%%% pages.”; LLabel labbel = new Laabel(labbelTeexxt, x + 5,5 y + 12, 220, 80, Font.TimesRoman, 12, Texe tAlign.C.Centter); label.Annglee = 8; PageNumbeeringgLabel pageNumLabelab = neww Page , 12, TeextAligign.CentC er); paga eEleementntss.Ad.Addd(paageNumLabel)); ppaggeElemenments.Addd(d(label)); } privprp ate voidoid AAddLine(Group pageElements, float x, floao t y) { // Addds a line to the pageElements AdddCCaptionAndRRectannglegle(pag(paga eeElemments + 5, y + 20, x + 220, y + 80, 3, RRgbColor.Gr.G eeen)); pageElemmentsn s.Addd(neww Linee(x + 222200, y + 20, x + 5, y + 80, 3, RgbColor.Green)); } private void AdddLLink((Grouup pageEElemments, float x, floaat yy) { // Adds a link to thethhe pagp eEleEleemen ynamicPDF.com.m ”; AddCaptionAnAndAnddRectanglan e((pageElementts, “LLink Page Elemment:nt:”, xx, y); LLabel labela = new Label(text, x + 5, y + 20, 215, 80, font, 12,2 RggbCoolor.Blue)e); laabel.Underline = true;rue Link linkk = new LLinnk(x + 5, y + 20, on(o “httpp://www.dynnamicppddf.coomm””))); pageEeElemments..Add(Ad labbeel); ppagepag Elementsnts.AAdd(link);k) } prp ivate void AddPath(Group pageElements, float x, float y) { // AAdds a path to the pageElemeents ceeTe.DynamicamiiccPPDPDF.PagegeElemlelemments.PatP h 20,0 RgbgbbColor.Blue, RgbCoolor.RRedd, 22, LineStyeS lee.Solidd, true); pathh.Su.SubbPaths.A.Adddd(neww LineSubPath(x + 215, y + 40)); path.SubPaths.Add(new CurveToSToSubPPathh(x + 108, y + 80, x + 160,, y + 800)); path.SubSubPathshs.A.AddAAd (new(ne CurveS ectecctangle(pageElemeents, “P“Path Page Element:””, x, yy);) pageEEleE meentss.AdAdd(path)th); } privaatee vooid AAddRectangle(Group pageElements, float x, float y) orderede ddList = ordeo redLedList.GetOverFlowLo List((x + 5, y + 200); AddCA ddCCaptiapa oonAndRect 222255, 110); page.EleemenGI<:@JI8DD<; List Page Elemmentn Overflow:””, x, y,, 2255, 110); page.Elemements.AddAdd(un(unorderedList); } private void AddTextFt ield(Group pageEeElemlemennts, flfloaat x, flooat y) { TextFFieldd txt = new TextFieldeld(“txtfnafnaame”,me x + 20, y+y + attedTeextArea(formattedHtml, x + 55, y + 20,202 215,15 60, FontFFamilyy.Heelvetica, 9, ffalse)se ; /// Sets the indent property formattedTextArea.Style.Paragraph.IndeIn nnt = 1188; AddCaptCap ionAndRectana gle(g e pagep eElemE ents, “FFormam ttedtedTeTextArearea P atteat dTeextArea Overflow Teext:”, x + 279, y);; pageEgeElements.AAdd(formattedTextAArea);a) // Createa e an overflow formatted text area for the overflow text FormmattedTextAxt reaMMaxaxLeLength =9= 9; txxt1.B1.Bordeded rCorColorr = RgbCololoor.BBlaack; txt1.Ba1 Ba MaM ximuum Lengthgth”;; pageEgeEElemeements.Add(txttxt1); TextFex ieldd txt2 = neew TeextField(“txxtf2name”, x + 330, y + 30, 150, 40); txt2.DefaultValue = “This is a TexxtFtFieldd whiichh goees tot the nexxt line if tht e textt exceeds wididth”; txt2.xt2 MMultMu iLinLine = RgR bCooolor.AliceBluee; txt2.T2. oolTip = “M“Multiline”; ppageEElemennts.AAdd(ttxt2); AddCapCaptiont AndRecctangle(pageElements, “TextField Form Page Element:”,, x, y, 5044, 85);; } prrivate voioid AddComC boFibo eld(Group pageElemeemenene tts,ts float x, fl , y + 4000, 150,, 2020);c; cb.Boro derCd olor = RgbColorr.BBlack; cb.BaackggrounndColor = RgbColoro .AliAliceBceBlue; cb.Font = Font.Helvetica; cb.FontSize = 12; cb.Itemsem .AAdd(“(“It( emm 1”);; ccb.IItemste .Add(“It““Item 2”); cb.Itemsems.Add(“Item 3”)); cb.IItems abble”].SSeleleclected = tru=FIe; cb.Edb itable = true; cb.ToToololTip =JG<<; “Editable Combo Box””; pageElgeE emements.Add(cb); ComboBox cb1 = new ComboBox(“cmb1namame”, x + 303,030 y + 44040, 150, 200); cb1.Bb1 orderColoor = Rgbg Coloor.Blr.BrBack;ack cb1.Bac .F.FontontSize = 12; cb1.Items.Add(“Item 1”); cb1.Items.AAdd(“Item 2”); ccb1.Items.Add((“Itemem 3”); cb1.Items.Add(“Item 4”); cb1.Items.Add(“Non-Editable”);”); cb1.Items[“Non-Eon-Editable”].Selectecc ed = true; cb1b1.E Editablee = faf lse;se cb1.ToolT errter.Coonvert(“http://www.google.com”, “Output.pdf”));Convverteer.Coonvert(GetDocD Path(“Do(“D cumentA.rtf”), “Output.pdf”);System.Diagnostics.Process.s.SStartt(“Ot(“ uutputt.pdf”);”); AsyncCoConverrtter aConvertere = newe AsyncCncConnverter(); aC veerted); aConverter.ConversionError += new ConversiionErroorEvventHHandler(aConveerteer_ConversionError); aConverter.Convert(@”C:\temp\DocumentA.rtA f”f””, , @”C:C \temte p\OuO tputA.pdf”); aCoa nverter.Convert(ert @”C:\teme p\Dop\D cumentB \Doc\D ummentC.rtf”, @”C:\temp\OutputC.pdf”); aConverrter.Coonverrt(“hhttp://www.yahoo.com”, @”C:\Temp\yahoo.pdf”); ConvC ersionOptions options = nnenewew Conversie s onOpOptiono s(720, 720, 72,7 true); ceTe.DynamicPm DF.Conveon rsionn.Co Co outpou ut.pdf”, optionso ); ceTe.DynamicPD F. Conversion.CConveerter.ConvCon ert(“C:\\temp\\\Document2.docx”, “C:\\temp\\op\ utput.pdf”, optioppt ons);s; stringing sampleHple tmlm = “

Thiss is a very simplee HTMLHT strs ingin inclinc udinud ng a T

;peXd`ZG;=Ç:fdgi\_\ej`m\G;=Jfclk`fej]fi%E

KIPFLIG;=JFCLK@FEJ=I<<KF;8PK nnn%;peXd`ZG;=%Zfd&\mXcn fiZXcc/''%-*(%,''-s"(+('%..)%/-)'

Untitled-1 1 9/8/11 11:56 AM BY ANDREW J. BRUST

JavaScript Diplomacy

JavaScript has been part of the Microsoft technology stable since Microsoft has even developed a framework whereby Hadoop the 1990s, and its prominence in the next wave of Microsoft MapReduce big data jobs can be written in JavaScript. Visual Basic products is huge. As those new products come to market, it’s and C# are not part of this framework; I guess there’s always an important to understand and take inventory of Redmond’s exception to the rule. But this one makes sense, given the Java and JavaScript adoption over the years. It turns out that the language’s pedigree of Hadoop. After all, Microsoft wants to contribute role at Microsoft reveals a lot about the company’s tendencies, things that will resonate with the Apache Hadoop community, and even as its personnel and products continue to change. JavaScript fi ts the bill. Perhaps most telling about Microsoft JavaScript implementations is that within them, Microsoft tends to couple the language with Function oliveBranch() one that’s more proprietary. For example, Microsoft support for And that raises an interesting point: Microsoft uses JavaScript when JavaScript goes back to the earliest versions of Internet Explorer, it wants to appeal to developers beyond its own ecosystem. I’m not but the browser also supported VBScript for client-side scripting, as sure if that’s been a premeditated strategy, or merely a pattern the it does to this day. The two languages have long coexisted on the company has followed, but I don’t think that matters. Whether server side, too. Active Server Pages, or ASP—the precursor to intentionally or habitually, Microsoft uses JavaScript to win hearts and today’s ASP.NET—supports both VBScript and JavaScript as well. minds from outside the fold, and uses its own languages to provide And this duality extends beyond the Web. Windows Script Host an even stronger platform for its more committed developer base. (WSH), for the creation of Windows scripts that took batch fi le The two-pronged strategy doesn’t always result in home runs. Few developers to the next level, also supported both languages. The Microsoft developers used VBScript in the browser, or JavaScript on successor to WSH, Windows PowerShell, is programmed with C# and the server (but the popularity of Node.js proves the idea is far from Visual Basic .NET, but it can host WSH scripts, including those written crazy). We’ll see whether Windows 8 applications are predominantly in JavaScript. Over and over, on the client as well as on the server, a developed with .NET languages and XAML, or JavaScript and HTML. Microsoft language and JavaScript have existed side-by-side. And, heck, maybe Agaves will turn out to be the next smart tags. But whether each JavaScript initiative succeeds, the reliable The Tradition Continues consistency of a JavaScript option has great value. It shows that The language partnership has continued in the Microsoft .NET Microsoft keeps itself in recruiting mode, and yet continues to take Framework era. While few people wrote them, the fi rst version of care of its own. A year ago, many developers feared JavaScript Visual Studio .NET supported the creation of .NET applications would be the only option for developing Windows 8 apps. I had a using JScript .NET as the programming language. That was 10 years hunch that wouldn’t be the case, and the Microsoft BUILD ago, but there’s still support for using JScript with .NET in Visual conference proved my hunch correct. Studio 2010. And, of course, the JavaScript editing and debugging With some analysis I now see where my hunch came from: For nearly experience in Visual Studio has built up nicely over the years. 20 years, Microsoft has used JavaScript as its emissary, but Redmond As Microsoft gets ready to rev nearly every product in its stack, has always served the home front as well. Whether by design or by the role of JavaScript is only increasing. Windows 8 applications, of accident, that strategy has worked. Hopefully it will continue to do course, can be developed in JavaScript and HTML5; the framework so, because Redmond shows no sign of changing course. VSM for the forthcoming LightSwitch HTML5 client apps uses JavaScript as its extensibility mechanism; apps (formerly code-named Andrew J. Brust is founder and CEO of Blue Badge Insights, an analysis, “Agaves”) for Offi ce and SharePoint 2013 are written in JavaScript strategy and advisory firm serving Microsoft customers and partners. Brust and use HTML as well. The companion language strategy continues, is also a Microsoft regional director and MVP; an advisor to the New York too. Windows 8 apps can be written in Visual Basic .NET and C# Technology Council; and coauthor of “Programming Microsoft SQL Server with XAML. LightSwitch desktop clients can be as well, and the two 2008” (Microsoft Press, 2008). A frequent speaker at industry events, Brust is .NET languages are still used for COM-based add-ins in Offi ce as co-chair of the Visual Studio Live! family of conferences and a contributing well as for conventional SharePoint development. editor to Visual Studio Magazine.

48 VISUAL STUDIO MAGAZINE · September 2012 · VisualStudioMagazine.com Untitled-2 1 8/10/12 11:54 AM Untitled-2 1 8/6/12 4:09 PM