MDN_1403DS

108
magazine THE MICROSOFT JOURNAL FOR DEVELOPER S MARCH 2014 VOL 29 NO 3 Asynchronous Programming................18 , 2 6

Transcript of MDN_1403DS

  • 8/21/2019 MDN_1403DS

    1/108

    magazine

    THE MICROSOFT JOURNAL FOR DEVELOPERS MARCH 2014 VOL 29 NO 3

    AsynchronousProgramming................18,

    http://www.devexpress.com/dashboard
  • 8/21/2019 MDN_1403DS

    2/108

    http://www.devexpress.com/superhero
  • 8/21/2019 MDN_1403DS

    3/108

    magazine

    THE MICROSOFT JOURNAL FOR DEVELOPERS MARCH 2014 VOL 29 NO 3

    Patterns for AsynchronousMVVM Applications: Data BindingStephen Cleary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    Asynchronous TCP Socketsas an Alternative to WCFJames McCaffrey . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

    A .NET Developer Primer forSingle-Page ApplicationsLong Le . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    Building a Netduino-BasedHID Sensor for WinRTDonn Morse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

    COLUMNSCUTTING EDGE

    A First Look at ASP.NET IdentityDino Esposito, page 6

    WINDOWS AZURE INSIDER

    The Windows Azure Service Busand the Internet of Things, Part Bruno Terkaly andRicardo Villalobos, page 12

    THE WORKINGPROGRAMMER

    Getting Started with Oak:Data Validation andWrapping UpTed Neward, page 62

    MODERN APPS

    A Look at the Hub Project andControl in Windows Store AppsRachel Appel, page 66

    DIRECTX FACTOR

    Triangles and TessellationCharles Petzold, page 74

    DONT GET ME STARTED

    The Peasants Are Revolting!David Platt, page 80

    AsynchronousProgramming................18,

  • 8/21/2019 MDN_1403DS

    4/108

    http://www.ontimenow.com/msdn
  • 8/21/2019 MDN_1403DS

    5/108

    http://www.ontimenow.com/msdn
  • 8/21/2019 MDN_1403DS

    6/108

    "lightning fast" Redmond Magazine

    "covers all data sources" eWeek

    "results in less than a second"InfoWorld

    hundreds more reviews and developercase studies at www.dtsearch.com

    The Smart Choice for Text Retrievalsince 1991

    www.dtSearch.com 1-800-IT-FINDS

    Instantly SearchTerabytes of Text

    Ask about fully-functional evaluations

    25+ fielded and full-text search types

    dtSearchs own document filterssupport Office, PDF, HTML, XML, ZIP,emails (with nested attachments), andmany other file types

    Supports databases as well as staticand dynamic websites

    Highlights hitsin all of the above

    APIs for .NET, Java, C++, SQL, etc.64-bit and 32-bit; Win and Linux

    dtSearch products:Desktop with Spider Web with Spider

    Network with Spider Engine for Win &.NETPublish(portable media) Engine for Linux

    Document filters also available for separatelicensing

    Printed in the USA

    magazineMARCH 2014 VOLUME29NUMBER3

    MOHAMMAD AL-SABTEditorial Director/[email protected]

    KENT SHARKEYSite Manager

    MICHAEL DESMONDEditor in Chief/[email protected]

    DAVID RAMELTechnical Editor

    SHARON TERDEMANFeatures Editor

    WENDY HERNANDEZGroup Managing Editor

    SCOTT SHULTZCreative Director

    JOSHUA GOULDArt Director

    SENIOR CONTRIBUTING EDITORDr. James McCaffreyCONTRIBUTING EDITORSRachel Appel, Dino Esposito, Kenny Kerr,Julie Lerman, Ted Neward, Charles Petzold, David S. Platt,Bruno Terkaly, Ricardo Villalobos

    Henry AllainPresident, Redmond Media Group

    Michele ImgrundSr. Director of Marketing & Audience EngagementTracy CookDirector of Online Marketing

    Irene FincherAudience Development Manager

    ADVERTISING SALES: 818-674-3416/[email protected]

    Dan LaBiancaVice President, Group PublisherChris KourtoglouRegional Sales ManagerDanna VedderRegional Sales Manager/Microsoft Account Manager

    David SeymourDirector, Print & Online ProductionSerena BarnesProduction Coordinator/[email protected]

    Neal VitalePresident & Chief Executive Ofcer

    Richard VitaleSenior Vice President & Chief Financial OfcerMichael J. ValentiExecutive Vice President

    Christopher M. CoatesVice President, Finance & AdministrationErik A. LindgrenVice President, Information Technology & Application Development

    David F. MyersVice President, Event Operations

    Jeffrey S. KleinChairman of the Board

    MSDN Magazine(ISSN 1528-4859) is published monthly by 1105 Media, Inc., 9201 Oakdale Avenue,Ste. 101, Chatsworth, CA 91311. Periodicals postage paid at Chatsworth, CA 91311-9998, and atadditional mailing ofces. Annual subscription rates payable in US funds are: U.S. $35.00, International$60.00. Annual digital subscription rates payable in U.S. funds are: U.S. $25.00, International $25.00.Single copies/back issues: U.S. $10, all others $12. Send orders with payment to: MSDN Magazine,P.O. Box 3167, Carol Stream, IL 60132, email [email protected] orcall (847) 763-9560.POSTMASTER:Send address changes to MSDN Magazine, P.O. Box 2166, Skokie, IL 60076. CanadaPublications Mail Agreement No: 40612608. Return Undeliverable Canadian Addresses to CirculationDept. or XPO Returns: P.O. Box 201, Richmond Hill, ON L4B 4R5, Canada.

    Printed in the U.S.A. Reproductions in whole or part prohibited except by written permission. Mailrequests to Permissions Editor, c/o MSDN Magazine, 4 Venture, Suite 150, Irvine, CA 92618.

    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 informationcontained herein is the readers sole responsibility. While the information has been reviewed for accuracy,there is no guarantee that the same or similar results may be achieved in all environments. Technicalinaccuracies may result from printing errors and/or new developments in the industry.

    Corporate Address:1105 Media, Inc., 9201 Oakdale Ave., Ste 101, Chatsworth, CA 91311,www.1105media.com

    Media Kits:Direct your Media Kit requests to Matt Morollo, VP Publishing, 508-532-1418 (phone),508-875-6622 (fax), [email protected]

    Reprints:For single article reprints (in minimum quantities of 250-500), e-prints, plaques and posters contact:PARS International, Phone: 212-221-9595, E-mail: [email protected], www.magreprints.com/QuickQuote.asp

    List Rental:This publications subscriber list, as well as other lists from 1105 Media, Inc., is availablefor rental. For more information, please contact our list manager, Jane Long, Merit Direct. Phone: 913-685-1301; E-mail:[email protected]; Web: www.meritdirect.com/1105

    All customer service inquiries should be sent to [email protected] orcall 847-763-9560.

    http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/http://www.dtsearch.com/mailto:[email protected]:[email protected]:818-674-3416/[email protected]:[email protected]:[email protected]:[email protected]://www.1105media.com/mailto:[email protected]:[email protected]://www.magreprints.com/mailto:[email protected]://www.magreprints.com/mailto:[email protected]://www.meritdirect.com/1105mailto:[email protected]:[email protected]://www.meritdirect.com/1105mailto:[email protected]://www.magreprints.com/mailto:[email protected]:[email protected]://www.1105media.com/mailto:[email protected]:[email protected]:818-674-3416/[email protected]:[email protected]:[email protected]://www.dtsearch.com/
  • 8/21/2019 MDN_1403DS

    7/108

    http://www.leadtools.com/
  • 8/21/2019 MDN_1403DS

    8/108

    msdn magazine4

    Dont Get Me Started columnist David Platt this month divesinto the revolt at Avon over the companys attempt to deploy anSAP-based order entry and customer management system. Ourback-page columnist takes his cues from many a muse, be they Nobel-winning physicists or cartoon characters from the funny pages. Andin that last regard, he and I share common inspiration.

    When Bill Wattersons brilliant Calvin and Hobbes comic strip

    exploded onto newspaper pages in , it was an unexpectedwell spring o insight and wisdom. As a parent, Ive marveled atWattersons ability to capture the simple genius o a boy at play. Andas editor in chie oMSDN Magazine, Ive ound that Wattersonsincorrigible -year-old, Calvin, and his loyal tiger, Hobbes, offerreal lessons or working developers. Here are just a ew.

    Test, Test, Test!Te Duplicator story arc is one of my favorites inthe -year run o the comic, but its a cautionary tale or developers.Calvin invented a box that creates copies o himsel, who he hopedwould do all his chores and school work. But Calvin never testedhis Duplicator, and he quickly aced a squad o ill-behaved dupes. ICalvin had designed a test to determine the actual behavior o the

    dupes his invention created, he might have saved himself a lot of work.Remediate: Calvin later developed

    an add-on or his Duplicator, called theEthicator, which let the operator set eachdupes personality to either Good or Evil.A simple patch saved what would other-wise have been a costly project ailure, asCalvin created a compliant, good-aligneddupe to do his chores.

    Fail Gracefully:Alas, the good Calvindupe tried to befriend Calvins nemesis Susie Derkins. I don't mindif he cleans my room and gets me good grades, Calvin griped, but

    when he starts talking to girls thats going too darn ar. Te unpre-dicted behavior led to an angry confrontation between Calvin andhis dupe, who suddenly cried Oops! Ive had an evil thought! and

    vanished in a puff of smoke. An exception-handling routine couldhave preserved the investment in the duplicate Calvin.

    Value ExtensibilityTen there was the ransmogrier, whichcould turn anyone into one of four target animals: eel, baboon, giantbug or dinosaur. Calvin showed great awareness allowing supportor additional targets, including an extensible UI to handle them.Te ransmogrier would later support worms, elephants, tigersand giant slugs. I wonder i he used XML?

    Leverage the platformBoth the Duplicator and ransmogrier

    as well as later Calvin inventions the Cerebral Enhance-O-ron andthe ime Machinewere built on a common, corrugated cardboardbox platform and permanent marker UI. Simple geometries, famil-iar materials and streamlined interfaces dened all four inventions.

    Dont Skimp on SecurityWhen Calvinand Hobbes created their exclusive club,Get Rid O Slimy girlS (G.R.O.S.S), theysecured entry to the club treehouse with along, multi-verse password about tigers,which ended with the line igers aregreat! Teyre the toast o the town. Liesalways better when a tigers around! Tat

    inal stanza alone is a -bit password,and I havent even described the dancing component. But Calvinstruggled to remember the verse, illuminating the deep challengeo balancing usability and security.

    Mind the org chart:G.R.O.S.S. offered a nal, valuable lessonthedanger posed by vague, shifing or tangled lines o authority. Calvinmay have been Dictator or Lie o G.R.O.S.S., but that didnt stopFirst iger Hobbes rom trying to usurp his authority. Constantmanagement reorgs created a volatile environment that producedhijacked meetings, failed initiatives and constant, internecine bicker-ing. G.R.O.S.S. never did mount a successful attack on Susie Derkins.

    Make Space for Creativity I Wattersons protagonists have

    one message or developers, its this: Dare to dream. Some oCalvins greatest insights occur while careening through the woodsin a toboggan or wagon. ake risks. Make mistakes. And, remem-ber, lifes always better when atigers around.

    Everything I Need to KnowI Learned from Calvin and Hobbes

    2014 Microsoft Corporation. All rights reserved.

    Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, you are not permitted to reproduce, store, or introduce into a retrieval system MSDN Magazineor any part of MSDNMagazine. If you have purchased or have otherwise properly acquired a copy of MSDN Magazinein paper format, you are permitted to physically transfer this paper copy in unmodied form. Otherwise, you are not permitted to transmitcopies of MSDN Magazine(or any part of MSDN Magazine) in any form or by any means without the express written permission of Microsoft Corporation.

    A listing of Microsoft Corporation trademarks can be found at microsoft.com/library/toolbar/3.0/trademarks/en-us.mspx. Other trademarks or trade names mentioned herein are the property of their respective owners.

    MSDN Magazineis published by 1105 Media, Inc. 1105 Media, Inc. is an independent company not afliated with Microsoft Corporation. Microsoft Corporation is solely responsible for the editorial contents of this magazine. Therecommendations and technical guidelines in MSDN Magazine are based on specic environments and congurations. These recommendations or guidelines may not apply to dissimilar congurations. Microsoft Corporation does not makeany representation or warranty, express or implied, with respect to any code or other information herein and disclaims any liability whatsoever for any use of such code or other information.MSDN Magazine, MSDN, and Microsoft logos areused by 1105 Media, Inc. under license from owner.

    Visit us at msdn.microsoft.com/magazine. Questions, comments or suggestions for MSDN Magazine? Send them to the editor: [email protected].

    MICHAEL DESMONDEDITORSNOTE

    http://msdn.microsoft.com/magazinemailto:[email protected]://msdn.microsoft.com/magazinemailto:[email protected]
  • 8/21/2019 MDN_1403DS

    9/108

    http://www.amyuni.com/
  • 8/21/2019 MDN_1403DS

    10/108

    msdn magazine6

    Offspring o the One ASP.NE approach to Web development thatcame with Visual Studio 1, the new ASP.NE Identity system is thepreerred way to handle user authentication in ASP.NE applications,whether based on Web Forms or MVC. In this column, Ill reviewthe basics o ASP.NE authentication and explore the new ASP.NEIdentity system rom the perspective o ASP.NE MVC developers.

    ASP.NE has long supported two basic types o authentication:Windows authentication and orms authentication. Windowsauthentication is seldom practical or public Web sites becauseits based on Windows accounts and access control list (ACL)tokens. Tus, it requires users to have a Windows account in theapplications domain, and it also assumes clients are connectingrom Windows-equipped machines. he other option is ormsauthentication, a widely adopted approach. Forms authenticationis based on a simple idea. For each access to a protected resource,the application ensures the request includes a valid authentica-tion cookie. I a valid cookie is ound, then the request is served asusual; otherwise, the user is redirected to a login page and asked

    to provide credentials. I these credentials are recognized as valid,then the application issues an authentication cookie with a givenexpiration policy. Its simple and it just works.

    Implementation o any orms authentication module cant happen

    without a distinct module that takes care o collecting user creden-tials and checking them against a database o known users. Writingthis membership subsystem has been one o the key responsibilitieso development teamsbut also one o the most annoying thingsever. Writing a membership system is not hard, per se. It mostlyrequires running a query against some sort o storage system andchecking a user name and password. Tis code is boilerplate andcan grow airly big as you add new authentication eatures such aschanging and recovering passwords, handling a changing numbero online users and so on. In addition, it has to be rewritten nearlyrom scratch i you change the structure o the storage or add moreinormation to the object that describes the user. Back in , with

    the release o ASP.NE ., Microsof addressed this problem by

    introducing right into the ramework a provider-based architectureand the membership provider. Instead o reinventing the wheelevery time, you could just derive membership rom the built-insystem and override only the unctions you intended to change.

    he ASP.NE native membership provider is a standalonecomponent that exposes a contracted interace. he ASP.NEruntime, which orchestrates the authentication process, is awareo the membership interace and can invoke whatever componentis conigured as the membership provider o the application.ASP.NE came with a deault membership provider based on anew given database schema. However, you could easily write yourown membership provider to basically target a different databasetypically, an existing database o users.

    Does that sound like a great chunk o architecture? In the begin-ning, nearly everybody thought so. In the long run, though, quitea ew people who repeatedly tried to build a custom membership

    provider started complaining about the verbosity o the interace.Actually, the membership provider comes in the orm o an inher-itable base class, MembershipProvider, which includes more than members marked as abstract. Tis means that or any new mem-bership provider you wanted to create, there were at least mem-bers to override. Worse yet, you didnt really need many o themmost o the time. A simpler membership architecture was needed.

    Introducing the Simple Membership Providero save you rom the burden o creating a custom membership layercompletely rom scratch, Microsof introduced with Visual Studio1 SP1 another option: the simple membership API. Originally

    available in WebMatrix and Web Pages, the simple membership

    A First Look at ASP.NET Identity

    CUTTINGEDGE DINO ESPOSITO

    public class AccountController : Controller{ public UserManager UserManager { get; private set; }

    public AccountController(UserManager manager) { UserManager = manager; }

    public AccountController() :this(new UserManager(

    new UserStore(new ApplicationDbContext()))) { }

    ...}

    Figure 1 Foundation of a Controller Based on ASP.NET Identity

    The simple membership API has

    become quite a popular way of

    managing authentication.

  • 8/21/2019 MDN_1403DS

    11/108

    http://www.devexpress.com/touch
  • 8/21/2019 MDN_1403DS

    12/108

    msdn magazine8 Cutting Edge

    API has become quite a popular way o managing authentication,especially in ASP.NE MVC. In particular, the Internet applicationtemplate in ASP.NE MVC uses the simple membership API tosupport user management and authentication.

    Looking under the hood o the API, it turns out that its just a

    wrapper on top o the classic ASP.NE membership API and itsSQL Server-based data stores. Simple membership lets you workwith any data store you have and requires only that you indicatewhich columns in the table serve as the user name and user ID.

    he major dierence rom the classic membership API is asignicantly shorter list o parameters or any methods. In addi-tion, you get a lot more reedom as ar as the schema o the mem-bership storage is concerned. As an example of the simplied API,consider what it takes to create a new user:

    WebSecurity.CreateUserAndAccount(username, password, new { FirstName = fname, LastName = lname, Email = email });

    You do most o the membership chores via the WebSecurity class.In ASP.NE MVC , however, the WebSecurity class expects to work

    with an extended membership provider, not a classic membership pro-vider. Te additional capabilities in an extended membership providerare related to dealing with OAuth accounts. As a result, in ASP.NEMVC , you have two parallel routes or membership implemen-tation: classic membership API using the MembershipProviderclass and simple membership API using the ExtendedMember-shipProvider class. Te two APIs are incompatible.

    Beore the arrival o Visual Studio 1 and ASP.NE MVC ,ASP.NE already offered quite a ew ways to handle user authen-tication. With orms authentication, you could rely on classicmembership, the simple membership API as dened in Web Pagesand a variety o custom membership systems. Consider the com-

    mon position among ASP.NE experts was that complex real-worldapplications require their own membership provider. More ofen

    than not, the main reason for having a custom membership systemwas to circumvent structural dierences between t he requireddatabase ormat and the ormat o the existing database o usercredentials, which might have been in use or years.

    Clearly, this wasnt a situation that could last forever. Te commu-

    nity o developers demanded with loud voices a unied system ormembership thats simple to use, narrowly focused and usable in thesame way from within any avor of ASP.NE. Tis idea weds togetherwell with the One ASP.NE approach pushed by Visual Studio 1.

    One Identity FrameworkTe purpose o authentication is getting the identity associated withthe current user. Te identity is retrieved and the provided credentialsare compared to records stored in a database. Subsequently, an iden-tity system such as ASP.NE Identity is based on two primary blocks:the authentication manager and the store manager. In the ASP.NEIdentity ramework, the authentication manager takes the orm o

    the UserManager class. Tis class basically provides a faadeor signing users in and out. Te store manager is an instance o theUserStore class. Figure 1shows the skeleton o an ASP.NEMVC account controller class thats based on ASP.NE Identity.

    Te controller holds a reerence to the authentication identitymanager, UserManager. Tis instance o UserManager is injectedinto the controller. You can use either an Inversion of Control (IoC)framework or the poor mans alternative, the dependency injection(DI) pattern, which uses two controllers, one o which gets adeault value(see Figure 1).

    Te identity store, in turn, is injected into the authenticationidentity manager, where its used to veriy credentials. Te identity

    store takes the orm o the UserStore class. his classresults rom the composition o multiple types:public class UserStore :IUserLoginStore,IUserClaimStore,IUserRoleStore,IUserPasswordStore,IUserSecurityStampStore,IUserStore,IDisposable where TUser : IdentityUser

    { }

    All interaces implemented by UserStore are bas icrepositories or optional user-related data such as passwords, roles,claims and, o course, user data. Te identity store needs to knowabout the actual data source, though. As shown in Figure 1, the datasource is injected in the UserStore class through the constructor.

    Storage of users data is managed through the Entity FrameworkCode First approach. Tis means you dont strictly need to create aphysical database to store your users credentials; you can, instead,dene a User class and have the underlying ramework create themost appropriate database to store such records.

    Te ApplicationDbContext class wraps up the Entity Frameworkcontext to save users data. Heres a possible deinition or theApplicationDbContext class:

    public class ApplicationDbContext : IdentityDbContext{}

    Basically, the database context o ASP.NE Identity handles thepersistence of a given user type. Te user type must implement the

    namespace Microsoft.AspNet.Identity.EntityFramework{ public class IdentityUser : IUser { public string Id { get; } public string UserName { get; set; } public string PasswordHash { get; set; } public string SecurityStamp { get; set; } public ICollection Roles { get; private set; } public ICollection Claims { get; private set; } public ICollection Logins { get; private set; }

    }}

    Figure 2 Definition of the Default User Class in ASP.NET Identity

    The Internet application

    template in ASP.NET MVC 4 uses

    the simple membership API to

    support user management

    and authentication.

  • 8/21/2019 MDN_1403DS

    13/108

    9March 2014msdnmagazine.com

    IUser interface or just inherit from IdentityUser. Figure 2presentsthe source code of the default IdentityUser class.

    Heres an example of a realistic custom user class you might wantto use in your applications:

    public class ApplicationUser : IdentityUser{ public DateTime Birthdate { get; set; }}

    Te use of Entity Framework Code First is a great move here as itmakes the structure of the database a secondary point. You still need

    one, but to create it, you can use code based on classes. In addition,you can use Entity Framework Code First migration tools to modifya previously created database as you make changes to the class behindit. (For more information on this, see the Code First Migrationsarticle in the MSDN Data Developer Center at bit.ly/Th92qf.)

    Authenticating UsersASP.NE Identity is based on the newest Open Web Interface for.NE (OWIN) authentication middleware. Tis means the typicalsteps of authentication (for example, creating and checking cookies)can be carried out through the abstract OWIN interfaces and notdirectly via ASP.NE/IIS interfaces. Support for OWIN requires

    the account controller to have another handy property, like this:private IAuthenticationManager AuthenticationManager{ get { return HttpContext.GetOwinContext().Authentication; }}

    The IAuthenticationManager interface is defined in theMicrosoft.Owin.Security namespace. his property is import-ant because it needs to be injected into any operation that involvesauthentication-related steps. Heres a typical login method:

    private async Task SignInAsync(ApplicationUser user, bool isPersistent){ var identity = await UserManager.CreateIdentityAsync(user,

    DefaultAuthenticationTypes.ApplicationCookie); AuthenticationManager.SignIn(new AuthenticationProperties() {

    IsPersistent = isPersistent }, identity);}

    Te method SignInAsync checks the specied user name andpassword against the store associated with the authenticationmanager. o register a user and add the user to the membershipdatabase, you use code like this:

    var user = new ApplicationUser() { UserName = model.UserName };var result = await UserManager.CreateAsync(user, model.Password);if (result.Succeeded)

    { await SignInAsync(user, isPersistent: false); return RedirectToAction("Index", "Home");}

    All in all, ASP.NE Identity provides a unified API for tasksrelated to authentication. For example, it unies the code requiredto authenticate against a proprietary database or a social networkOAuth-based endpoint. Figure 3shows a fragment of the codeyou need to authenticate users against an external login engine.Te code in Figure 3gets called once the OAuth authentication(for example, against Facebook) has been completed successfully.

    The Bottom LineAs I see things, ASP.NE Identity is an overdue solution that shouldhave come years ago. Te key issue concerning ASP.NE Identityright now is the development team is trying to come up with aprogramming interface thats generic and testable enough to lastfor a long timeor at least until something newer and better showsup in the industry.

    For the foreseeable future, ASP.NE Identity promises to beas good as old-fashioned membership was perceived to be adecade ago. Personally, I like the expressiveness of the API and theattempt to fuse together different forms of authenticationbuilt-inand OAuth-based, for example. Another great plus is the integra-tion with OWIN, which makes it somewhat independent from aspecic runtime such as IIS/ASP.NE.

    ASP.NE Identity is bound to Visual Studio 1, but its alsoexpected to have an autonomous life of its own when it comes tofuture builds and releases. Ive just scratched the surface of the newidentity API here. Stay tuned for newer builds and releases!

    DINOESPOSITOis the author o Architecting Mobile Solutions or the Enterprise(Microsof Press, ) and the up coming Programming ASP.NET MVC (Microsof Press). A technical evangelist or the .NET and Android platorms at Jet-Brains and requent speaker at industry events worldwide, Esposito shares his visiono sofware at sofwarecents.wordpress.com and on Twitter at twitter.com/despos.

    THANKSto the following technical expert for reviewing this article:Pranav Rastogi (Microsof)

    ASP.NET Identity is bound toVisual Studio 2013, but its also

    expected to have an autonomous

    life of its own when it comes to

    future builds and releases.

    public async Task ExternalLoginCallback( string loginProvider, string returnUrl){ ClaimsIdentity id = await UserManager .Authentication

    .GetExternalIdentityAsync(AuthenticationManager);var result = await UserManager

    .Authentication .SignInExternalIdentityAsync( AuthenticationManager, id); if (result.Success) return RedirectToLocal(returnUrl); else if (User.Identity.IsAuthenticated) { result = await UserManager .Authentication .LinkExternalIdentityAsync( id, User.Identity.GetUserId()); if (result.Success) return RedirectToLocal(returnUrl); else return View("ExternalLoginFailure");

    }}

    Figure 3 Finalizing the Authentication Process

    through an External Endpoint

    http://www.msdnmagazine.com/http://www.bit.ly/Th92qfhttp://www.bit.ly/Th92qfhttp://www.bit.ly/Th92qfhttp://www.wordpress.com/http://www.twitter.com/desposhttp://www.twitter.com/desposhttp://www.wordpress.com/http://www.bit.ly/Th92qfhttp://www.msdnmagazine.com/
  • 8/21/2019 MDN_1403DS

    14/108

    http://www.aspose.com/
  • 8/21/2019 MDN_1403DS

    15/108

    http://www.aspose.com/
  • 8/21/2019 MDN_1403DS

    16/108

    msdn magazine12

    In our last column(msdn.microsoft.com/magazine/dn574801 ), we discussedthe current technology landscape or machine-to-machine (MM)computing, which reers to technologies that interconnect devices,usually or industrial instrumentation, in the orm o sensors or meters.Te prolieration o affordable and easy-to-program tiny computershas expanded this concept into whats called the Internet-o-Tings

    (Io), opening the door to scenarios where even ordinary homeappliances can be controlled or used as sources o inormation togenerate events. Tis way, it isnt diffi cult to send alerts when its timeto replenish the ridge, automatically close the window blinds asnight alls or set the thermostat based on the amily habits.

    We also made the case or using the Windows Azure Service Bus ordevice connectivity, as an alternative to using a VPN, when trying tosolve the addressability, security, and perormance concerns associatedwith deploying a large number o sensors or meters. Tis is becomingincreasingly relevant considering that, according to the latest BI Intel-ligence report rom Business Insider, there will be more than billionconnections directly related to the Io by the year 1(read.bi/18L5cg8).

    Using a designated Service Bus queue or topic or a deviceprovides an elegant way to incorporate resiliency and occasionalconnectivity or Io applications. In this article, well walk througha hands-on Windows Azure implementation that illustrates theseconcepts, designing a Service Bus blueprint with device queues,deploying a listening worker role in Cloud Services, and program-ming an Arduino device that executes commands sent remotelyby mobile clients, as shown in Figure 1.

    I you look at the diagram, the Windows Azure Service Buscomponent becomes the centerpiece o the design, providing theauthentication, message distribution and scalability to supportthe multiple devices that will be sending data or receiving remote

    commands. Te Service Bus is available in all Microsof datacentersthat offer Windows Azure services, and its backed up by a highlyredundant storage i nrastructure. Also, like all other WindowsAzure components, it offers an open and easy-to-understand RESinterace, along with multiple SDKs (Microsof .NE Framework,Java, PHP, Ruby, among others) built on top o it.

    In our proposed architecture, devices talk to a .NE applicationrunning on Windows Azure Cloud Services, which acts as a gate-way to the Service Bus in order to simpliy the communicationprocess with its assigned queue. his approach ully enablesany o the our Io communication patterns described in ourprevious column: elemetry, Inquiry, Command and Notication.

    Here, well implement a scenario in which a mobile device sendsa command to another device in order to execute an actioninthis case, turn an LED on or off. One o the benets o this solu-tion is that i the device is temporarily offl ine, it can pick up thecommands whenever it reconnects to the Internet. You can alsoset up an expiration time in a message to avoid the execution o atask at an inconvenient moment or schedule messages to be sentat a specic time in the uture.

    For this example, well use the well-known, well-documentedArduino device, as described in our previous column. For themobile client portion o the proo-o-concept, well create aWindows Phone application.

    Heres our simple scenario:1. When the Arduino device is started, it sends an identica-tion signal to the gateway application running on WindowsAzure Cloud Services. Te gateway creates a Service Bus

    The Windows Azure Service Bus and theInternet of Things, Part 2

    Code download available at msdn.microsoft.com/magazine/msdnmag0314.

    WINDOWSAZUREINSIDERBRUNO TERKALY AND

    RICARDO VILLALOBOS

    BUILD A FREE DEV/TEST SANDBOX IN THE CLOUD

    MSDN subscribers can quickly spin up a dev/test environment on

    Windows Azure at no cost. Get up to $150 in credits each month!

    aka.ms/msdnmag

    Figure1An Internet-of-Things Architecture Using theWindows Azure Service Bus

    TCP Connection

    ArduinoTCP Connection

    TCP Connection

    REST Interface/SDKs

    Windows Azure Service Bus

    Windows AzureCloud Service

    Mobile and Desktop Devices

    http://msdn.microsoft.com/magazine/dn574801http://msdn.microsoft.com/magazine/dn574801http://msdn.microsoft.com/magazine/dn574801http://read.bi/18L5cg8http://read.bi/18L5cg8http://read.bi/18L5cg8http://msdn.microsoft.com/magazine/msdnmag0314http://aka.ms/msdnmaghttp://msdn.microsoft.com/magazine/msdnmag0314http://aka.ms/msdnmaghttp://read.bi/18L5cg8http://msdn.microsoft.com/magazine/dn574801
  • 8/21/2019 MDN_1403DS

    17/108

    1March 2014msdnmagazine.com

    queue for the device in case it doesnt exist, and establishesa CP connection, ready to send commands.

    . A Windows Phone application sends a command to theWindows Azure Service Bus queue assigned to the device.

    . Te message remains in the queue until the gateway appli-

    cation picks it up and sends the command to the Arduinodevice via the established CP connection.. Te Arduino device turns the LED on or off based on

    the command.Lets look at the steps to make this happen, one by one.Step 1: Create the Windows Azure Service Bus Namespace

    Using your Windows Azure credentials (you can request a trialaccount at bit.ly/1atsgSa), log in to the Web portal and click on theSERVICE BUS section (see Figure 2). Select the CREAE option,and enter a name for your namespace. Ten, click on CONNEC-ION INFORMAION and copy the text in the Connection Stringbox, which youll need later.

    Step 2: Create the Gateway Application and Deploy to WindowsAzure Cloud ServicesCode for the gateway application, whichretrieves messages from the Service Bus queue and relays the commandsto the Arduino device, is included with the code download (availableat msdn.microsoft.com/magazine/msdnmag0314).Its based on the work ofClemens Vaster, who kindly contributed his guidance and expertiseto this article. His original project can be found at bit.ly/L0uK0v .

    Before we dive into this code, be sure you have Visual Studio1 installed, along with version . of the Windows Azure SDKfor .NE(bit.ly/JYXx5n). Te solution includes three different projects:

    ArduinoListenercontains the main WorkerRole code. ConsoleListenerthe console version of the Arduino-

    Listener, for local testing. MSDNArduinoListenerthe Windows Azure deploy-ment project for ArduinoListener.

    If you inspect the ServiceConguration.cscfg les (for both cloudand local deployment) for the MSDNArduinoListener project,youll see a setting that stores the connection string for the ServiceBus. Replace its value with the one obtained in Step 1. Te rest isalready congured for the solution to work, including the deni-

    tion of port 11 for receiving connections from the devices. Next,open the WorkerRole.cs le in the ArduinoListener project, wherethe main code is located.

    Tere are four main sections to analyze.First, a cpListener is created, and connections from devices

    are accepted:var deviceServer = new TcpListener(deviceEP);deviceServer.Start(10);try{ do { TcpClient connection = await deviceServer.AcceptTcpClientAsync(); if (connection != null) { ...

    Once a connection with the device has been established, a Network-Stream is dened and set to listening mode. Te readBuffer variablewill contain the identier value sent by each Arduino device:

    NetworkStream deviceConnectionStream = connection.GetStream();var readBuffer = new byte[64];if (await deviceConnectionStream.ReadAsync(readBuffer, 0, 4) == 4){ int deviceId = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(readBuffer, 0)); ...

    Next, a queue is created based on the deviceId value (in case itdoesnt exist), and a message receiver object is dened(see Figure3). Ten, the device queue receiver is set to asynchronous mode topull messages (commands from the queue). Tis queue will store

    commands sent by mobile devices, such as a Windows Phone.When a message is received in the queue, its content is inspected andif it matches the ON or OFF commands, the information is written

    to the connection stream establishedwith the device(see Figure 4).

    Notice that the message isntremoved from the queue (message.CompleteAsync) unless the writingoperation to the device connectionstream is successful. Also, in orderto keep the connection alive, thedevice is expected to send a ping

    heartbeat. For this proof of concept,we arent expecting conrmation fromthe device when it receives the message.In a production system, however, thiswould be required to comply with thecommand pattern.

    Step 3: Deploy the Arduino-

    Listener Windows Azure Project

    to Cloud Services Deploying theArduinoListener to Windows Azureis extremely simple. In Visual Studio1, right-click on the MSDN-

    ArduinoListener project andselect the Publish option. Youll ndFigure 2Creating the Windows Azure Service Bus Namespace

    http://www.msdnmagazine.com/http://www.bit.ly/1atsgSahttp://www.bit.ly/1atsgSahttp://www.bit.ly/1atsgSahttp://msdn.microsoft.com/magazine/msdnmag0314http://msdn.microsoft.com/magazine/msdnmag0314http://msdn.microsoft.com/magazine/msdnmag0314http://www.bit.ly/L0uK0vhttp://www.bit.ly/L0uK0vhttp://www.bit.ly/L0uK0vhttp://www.bit.ly/JYXx5nhttp://www.bit.ly/JYXx5nhttp://www.bit.ly/JYXx5nhttp://www.bit.ly/JYXx5nhttp://www.bit.ly/L0uK0vhttp://msdn.microsoft.com/magazine/msdnmag0314http://www.bit.ly/1atsgSahttp://www.msdnmagazine.com/
  • 8/21/2019 MDN_1403DS

    18/108* Offer valid for a limited time only. Complete packages come with a 30 day money back guarantee and no minimum contract term. The $7.99 per month price reflect s a 12 month

    pre-payment option for the 1&1 Online Store Starter package. After 12 months, regular price of $9.99 per month applies. Some features listed are only available with package upgrade.

    DOMAINS |E-MAIL |WEB HOSTING |eCOMMERCE |SERVERS

    1&1 NEW

    eCOMSELL MORE WITH APROFESSIONAL DESIGN.

    Whether beginner or professional, create

    your store online in a few easy steps

    Choose from over a hundred high-qualitydesigns and templates between industries

    Store links easily with an existing domainor your new included domain (free)*

    Whether PC, tablet or smartphone yourshop will be displayed optimally onall devices

    http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/
  • 8/21/2019 MDN_1403DS

    19/108

    START SELLING NOW!

    Visit www.1and1.com for billing information and full promotional details. Program and pricing specifications and availability subject to change without notice. 1&1 and the 1&1 logo are

    trademarks of 1&1 internet, all other trademarks are the propert y of their respective owne rs. 2014 1&1 Internet. All right s reserved.

    Call1 (877) 461-2631

    TEST30 DAY MONEY

    BACK GUARANTEE

    MONTHFLEXIBLE PAYMENT

    OPTIONS

    CALLSPEAK WITH AN

    EXPERT 24/7

    1and1.com

    MERCE1&1 ONLINE STORECOMPLETE PACKAGESstarting at

    Try now! 30 day money back guarantee.$7.99month*

    MORE POSSIBILITIES.

    MORE SUCCESS.

    Your shop can grow with yourbusiness

    Target customers with specialpromotions and cross selling

    Product rating capability: Buildtrust by letting customers sharefeedback

    Sell internationally: Wide selectionof languages, currencies and

    payment options

    MAXIMUM RELIABILITY.

    PROFESSIONAL SUPPORT.

    Convenient shipping processingvia UPS, FedEx, etc.

    Reliability through geo-redundant operation in twoseparate 1&1 Data Centers

    24/7 expert customer serviceby experienced eCommerceprofessionals

    FIND CUSTOMERS.

    KEEP CUSTOMERS.

    Search engine optimization (SEO):rank higher on Google and othersearch engines

    Easy synchronization with Amazon,Ebay, and more

    Easily create your own Facebook Store

    Create customer loyalty by providingfree newsletters and coupons

    http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/http://www.1and1.com/
  • 8/21/2019 MDN_1403DS

    20/108

    msdn magazine16 Windows Azure Insider

    specic instructions or the Publish Windows Azure ApplicationWizard atbit.ly/1iP9g2p. Afer completing the wizard, you end up witha cloud service located at xyz.cloudapp.net. Record this name, asyoull need it when you create the Arduino client in the next step.

    Step 4: Program the Arduino Device to Talk to the Gateway

    (Listener) Arduino devices offer a rich interace or perorming net-work operations using a simple Web client object. For our prototype,we decided to use the Arduino Uno R model(bit.ly/18ZlcM8), alongwith its corresponding Ethernet shield (bit.ly/1do6eRD). o install,interact and program Arduino devices using Windows, ollow theguide at bit.ly/1dNBi9R. Youll end up with an easy-to-use IDE (calledthe Arduino application), where you can write programs (calledsketches) using JavaScript, as shown in Figure 5.

    Figure 6 shows the sketch or interacting with the ArduinoListener created in Step , and now deployed in Windows Azure.

    Sketches or the Arduino have two main sections: setup andloop. Instructions in the setup section are executed once, and this

    is where variables are initialized and connections established. Inour example, the Ethernet client and related values are dened, aserial connection (or debugging purposes) is established, and thepin where the LED is connected is initialized as an output port.

    Code in the loop section is executed constantly, and it includestwo main blocks based on the statuso the CP connection between theArduino device and the listener run-ning in Windows Azure Cloud Services:connected or disconnected. When theconnection is established or the rsttime, a stopWatch object is started to

    keep track o the time elapsed or theconnection. Also, the device identieris sent to the listener, to be used as thename o the queue where messages andcommands will be stored.

    he code block that handles theArduino behavior afer the connec-tion has been established keeps tracko the time elapsed since the connec-tion was created, pinging the listenerevery , ms, to keep the con-nection alive when no commands are

    received. Tis code also tries to readdata rom the listener, putting the

    data into the bu array when it arrives. I a value o 1 is detected,the LED is turned on, i the value is , the LED is turned off. Testopwatch object is reset afer each command.

    Once the sketch has been uploaded to the device, the code runs onthe Arduino controller in an innite loop, trying to connect to a cloudservice. When connected, it orwards the device id so the cloud serviceknows to which device its talking. Ten the code begins to read inputrom the cloud service, telling the device whether to turn on or off theLED light (in this case, its connected to digital port o the device).

    Step 5: Creating a Windows Phone Client to Send to Device

    QueueInteracting with the device is as simple as sending messagesto the device queue. As we mentioned at the beginning o the

    article, the Windows Azure Service Bus provides a RES interacethat lets you interact with it rom multiple programming languages.Because theres no offi cial SDK or Windows Phone developers, weused one o the examples rom the Windows Phone community,which shows how to authenticate and interact with the Service

    Bus using HP requests and theWebClient object. he source codeis also included with the code down-load, in the Visual Studio 1 projectcalled MSDNArduinoClient. Figure7shows the clients main screen, romwhich you send commands to the

    Arduino device.Creating similar clients or other

    mobile devices (including iOS andAndroid) wouldnt be diffi cult, as mosto them provide libraries to gener-ate RES commands using HPrequest clients. Moreover, its possibleto directly interact with the WindowsAzure Service Bus using traditionallanguages such as Java, PHP or Ruby,which simplies this process. TeseSDKs are published under an open

    source license, and can be oundat github.com/WindowsAzure .

    if (message != null){ Stream stream = message.GetBody(); StreamReader reader = new StreamReader(stream); string command = reader.ReadToEnd();

    if (command != null) { switch (command.ToUpperInvariant()) { case "ON": await deviceConnectionStream.WriteAsync(OnFrame, 0, OnFrame.Length); await message.CompleteAsync(); break; case "OFF": await deviceConnectionStream.WriteAsync(OffFrame, 0, OffFrame.Length); await message.CompleteAsync(); break; } }}

    Figure 4 Writing to the Connection Stream

    Figure 5 The Arduino Application

    var namespaceManager = NamespaceManager.CreateFromConnectionString(RoleEnvironment.GetConfigurationSettingValue("serviceBusConnectionString"));if (!namespaceManager.QueueExists(string.Format("dev{0:X8}", deviceId))){ namespaceManager.CreateQueue(string.Format("dev{0:X8}", deviceId));

    }var deviceQueueReceiver = messagingFactory.CreateMessageReceiver( string.Format("dev{0:X8}", deviceId), ReceiveMode.PeekLock);do{ BrokeredMessage message = null; message = await deviceQueueReceiver.ReceiveAsync(); ...

    Figure 3Creating a Queue

    http://www.bit.ly/1iP9g2phttp://www.bit.ly/1iP9g2phttp://www.bit.ly/1iP9g2phttp://www.bit.ly/18ZlcM8http://www.bit.ly/18ZlcM8http://www.bit.ly/18ZlcM8http://www.bit.ly/1do6eRDhttp://www.bit.ly/1do6eRDhttp://www.bit.ly/1do6eRDhttp://www.bit.ly/1dNBi9Rhttp://www.bit.ly/1dNBi9Rhttp://www.bit.ly/1dNBi9Rhttp://www.github.com/WindowsAzurehttp://www.github.com/WindowsAzurehttp://www.github.com/WindowsAzurehttp://www.github.com/WindowsAzurehttp://www.bit.ly/1dNBi9Rhttp://www.bit.ly/1do6eRDhttp://www.bit.ly/18ZlcM8http://www.bit.ly/1iP9g2p
  • 8/21/2019 MDN_1403DS

    21/108

    1March 2014msdnmagazine.com

    Wrapping UpBuilding an Internet-of-Things architectureusing the Windows AzureService Bus to managedevices and services con-nections provides an easyway to secure, scale andaddress clients individ-

    ually without incurringcostly VPN solutions, withthe benefit of efficientlyhandling occasionallydisconnected scenarios.Queues act as dedicatedmailboxes where messagesbetween devices andservices are exchanged,supporting the differentcommunication use casesand patterns commonly

    found in the eld. WindowsAzure provides a reliable,

    geo-distributed and robust infrastructure for deploying the servicesrequired with a high volume of interconnected sensors andmetersa trend that will continue to grow in the years ahead.

    BRUNOTERKALYis a developer evangelist or Microsof. His depth o knowledgecomes rom years o experience in the eld, writing code using a multitude oplatorms, languages, rameworks, SDKs, libraries and APIs. He spends timewriting code, blogging and giving live presentations on building cloud-basedapplications, specically using the Windows Azure platorm. You can read hisblog at blogs.msdn.com/b/brunoterkaly.

    RICARDOVILLALOBOSis a seasoned sofware architect with more than yearso experience designing and creating applications or companies in multipleindustries. Holding different technical certications, as well as a masters degreein business administration rom the University o Dallas, he works as a cloudarchitect in the DPE Globally Engaged Partners team or Microsot, helpingcompanies worldwide to implement solutions in Windows Azure. You can readhis blog at blog.ricardovillalobos.com.

    Terkaly and Villalobos jointly present at large industry conerences. Theyencourage readers o Windows Azure Insider to contact them or availability.Terkaly can be reached at [email protected] and Villalobos can be [email protected].

    THANKSto the following Microsoft technical experts for reviewing this article:Abhishek Lal and Clemens Vasters

    Figure6The Arduino Device Code

    #include #include #include // Enter a MAC address and IP address for your controller below.// The IP address will be dependent on your local network,// and it's optional if DHCP is enabled.byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xBC, 0xAE };static const byte deviceId[] = { 0x00, 0x00, 0x00, 0x01 };static const uint8_t ACK = 0x01;static const int LED_PIN = 8;int connected = 0;EthernetClient client;StopWatch stopWatch;long pingInterval = 200000;void setup(){ Serial.begin(9600); Serial.println("Initialized"); Ethernet.begin(mac); pinMode(LED_PIN, OUTPUT);}void turnLedOn(){ digitalWrite(LED_PIN, HIGH);}void turnLedOff(){ digitalWrite(LED_PIN, LOW);}void loop(){if ( connected == 0)

    { Serial.println("Trying to connect"); char* host = "xyz.cloudapp.net"; client.setTimeout(10000); connected = client.connect(host, 10100); if (connected)

    { Serial.println( "Connected to port, writing deviceId and waiting for commands..."); client.write(deviceId, sizeof(deviceId)); stopWatch.start(); }

    else { Serial.println("Connection unsuccessful"); client.stop(); stopWatch.reset(); } } if (connected == 1) { if (stopWatch.elapsed() > pingInterval) { Serial.println("Pinging Server to keep connection alive..."); client.write(deviceId, sizeof(deviceId)); stopWatch.reset();

    stopWatch.start(); } byte buf[16]; int readResult = client.read(buf, 1);

    if (readResult == 0){

    Serial.println("Can't find listener, disconnecting..."); connected = 0; stopWatch.reset(); } else if (readResult == 1) { Serial.println("Data acquired, processing..."); switch ( buf[0] ) { case 1: Serial.println("Command to turn led on received..."); turnLedOn(); break; case 2:

    Serial.println("Command to turn led off received..."); turnLedOff(); break; } stopWatch.reset(); stopWatch.start(); } }}

    Figure7The Windows Phone Cli-ent Interface

    http://www.msdnmagazine.com/http://blogs.msdn.com/b/brunoterkalyhttp://blog.ricardovillalobos.com/mailto:[email protected]:[email protected]:[email protected]:[email protected]://blog.ricardovillalobos.com/http://blogs.msdn.com/b/brunoterkalyhttp://www.msdnmagazine.com/
  • 8/21/2019 MDN_1403DS

    22/108

    msdn magazine18

    Asynchronous code usingthe async and await keywords

    is transorming the way programs are written, and with goodreason. Although async and await can be useul or server sofware,most o the current ocus is on applications that have a UI. Forsuch applications, these keywords can yield a more responsive UI.However, its not immediately obvious how to use async and awaitwith established patterns such as Model-View-ViewModel (MVVM).Tis article is the rst in a short series that will consider patternsor combining async and await with MVVM.

    o be clear, my rst article on async, Best Practices in Asyn-chronous Programming(msdn.microsoft.com/magazine/jj991977 ), wasrelevant to all applications that use async/await, both client andserver. Tis new series builds on the best practices in that article

    and introduces patterns specically or client-side MVVM appli-cations. Tese patterns are just patterns, however, and may notnecessarily be the best solutions or a specic scenario. I you nda better way, let me know!

    As o this writing, the async and await keywords are supported

    on a wide number o MVVM platorms: desktop (WindowsPresentation Foundation [WPF] on the Microsof .NET Framework and higher), iOS/Android (Xamarin), Windows Store (Windows and higher), Windows Phone (version . and higher), Silverlight(version and higher), as well as Portable Class Libraries (PCLs)targeting any mix o these platorms (such as MvvmCross). Tetime is now ripe or async MVVM patterns to develop.

    Im assuming youre somewhat amiliar with async and awaitand quite amiliar with MVVM. I thats not the case, there are anumber o helpul introductory materials available online. My blog(bit.ly/19IkogW) includes an async/await intro that lists additionalresources at the end, and the MSDN documentation on async is

    quite good (search or Task-based Asynchronous Programming).For more inormation on MVVM, I recommend pretty muchanything written by Josh Smith.

    A Simple ApplicationIn this article, Im going to build an incredibly simple application,as Figure 1shows. When the application loads, it starts an HPrequest and counts the number o bytes returned. he HPrequest may complete successully or with an exception, and theapplication will update using data binding. Te application is ullyresponsive at all times.

    First, though, I want to mention that I ollow the MVVM pattern

    rather loosely in my own projects, sometimes using a properdomain Model, but more oten using a set o services and data

    A S YN C P ROG RA M M I N G

    Patterns forAsynchronousMVVM Applications:Data BindingStephen Cleary

    This article discusses:

    Combining asynchronous programming with the MVVM pattern

    Developing an asynchronous data-bound property

    Common mistakes with ViewModels

    An approach thats data-binding friendly

    Technologies discussed:

    Asynchronous Programming, MVVM

    http://msdn.microsoft.com/magazine/jj991977http://msdn.microsoft.com/magazine/jj991977http://msdn.microsoft.com/magazine/jj991977http://www.bit.ly/19IkogWhttp://www.bit.ly/19IkogWhttp://www.bit.ly/19IkogWhttp://www.bit.ly/19IkogWhttp://msdn.microsoft.com/magazine/jj991977
  • 8/21/2019 MDN_1403DS

    23/108

    1March 2014msdnmagazine.com

    transfer objects (essentially a data access layer) instead of an actualModel. Im also rather pragmatic when it comes to t he View; Idont shy away from a few lines of codebehind if the alternative isdozens of lines of code in supporting classes and XAML. So, whenI talk about MVVM, understand that Im not using any particularstrict denition of the term.

    One of the rst things you have to consider when introducing

    async and await to the MVVM pattern is identifying which parts ofyour solution need the UI threading context. Windows platformsare serious about UI components being accessed only from the UIthread that owns them. Obviously, the view is entirely tied to theUI context. I also take the stand in my applications that anythinglinked to the view via data binding is tied to the UI context.Recent versions of WPF have loosened this restriction, allowingsome sharing of data between the UI thread and backgroundthreads (for example, BindingOperations.EnableCollection-Synchronization). However, support for cross-thread data bindingisnt guaranteed on every MVVM platform (WPF, iOS/Android/Windows Phone, Windows Store), so in my own projects I just

    treat anything data-bound to the UI as having UI-thread affi nity.As a result, I always treat my ViewModels as though theyre

    tied to the UI context. In my applications, the ViewModel is moreclosely related to the View than the Modeland the ViewModellayer is essentially an API for t he entire application. he Viewliterally provides just the shell of UI elements in which the actualapplication exists. Te ViewModel layer is conceptually a testableUI, complete with a UI thread affi nity. If your Model is an actualdomain model (not a data access layer) and theres data bindingbetween the Model and ViewModel, then the Model itself alsohas UI-thread affi nity. Once youve identied which layers haveUI affi nity, you should be able to draw a mental l ine between the

    UI-affi ne code (View and ViewModel, and possibly the Model)

    and the UI-agnostic code (probably the Model and denitely allother layers, such as services and data access).

    Furthermore, all code outside the View layer (that is, the View-Model and Model layers, services, and so on) should not depend onany type tied to a specic UI platform. Any direct use of Dispatcher(WPF/Xamarin/Windows Phone/Silverlight), CoreDispatcher

    (Windows Store), or ISynchronizeInvoke (Windows Forms) is abad idea. (SynchronizationContext is marginally better, but barely.)For example, theres a lot of code on the Internet that does someasynchronous work and then uses Dispatcher to update the UI; amore portable and less cumbersome solution is to use await forasynchronous work and update the UI without using Dispatcher.

    ViewModels are the most interesting layer because they have UIaffi nity but dont depend on a specic UI context. In this series, Illcombine async and MVVM in ways that avoid specic UI typeswhile also following async best practices; this rst article focuseson asynchronous data binding.

    Asynchronous Data-Bound Propertieshe term asynchronous property is actually an oxymoron.Property getters should execute immediately and retrieve currentvalues, not kick off background operations. Tis is likely one of thereasons the async keyword cant be used on a property getter. If yound your design asking for an asynchronous property, considersome alternatives rst. In particular, should the property actuallybe a method (or a command)? If the property getter needs to kickoff a new asynchronous operation each time its accessed, thats nota property at all. Asynchronous methods are straightforward, andIll cover asynchronous commands in another article.

    In this article, Im going to develop an asynchronous data-bound

    property; that is, a d ata-bound property that I update with theresults of an async operation. One common scenario is when aViewModel needs to retrieve data from some external source.

    As I explained earlier, for my sample application, Im going todene a service that counts the bytes in a Web page. o illustratethe responsiveness aspect of async/await, this service will alsodelay a few seconds. Ill cover more realistic asynchronous servicesin a later article; for now, the service is just the single methodshown in Figure 2.

    Figure 1The Sample Application

    using System;using System.Net.Http;using System.Threading.Tasks;public static class MyStaticService{ public static async Task CountBytesInUrlAsync(string url) { // Artificial delay to show responsiveness. await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);

    // Download the actual data and count it. using (var client = new HttpClient()) { var data = await client.GetByteArrayAsync(url).ConfigureAwait(false); return data.Length; } }

    }

    Figure 2 MyStaticService.cs

    http://www.msdnmagazine.com/http://www.msdnmagazine.com/
  • 8/21/2019 MDN_1403DS

    24/108

    msdn magazine20 Async Programming

    Note that this is considered a service, so its UI-agnostic. Becausethe service is UI-agnostic, it uses CongureAwait(false) every timeit does an await (as discussed in my other article, Best Practices inAsynchronous Programming).

    Lets add a simple View and ViewModel that starts an HPrequest on startup. Te example code uses WPF windows with

    the Views creating their ViewModels on construction. Tis is justfor simplicity; the async principles and patterns discussed in thisseries of articles apply across all MVVM platforms, frameworksand libraries. he View for now will consist of a single mainwindow with a single label. Te XAML for the main View just bindsto the UrlByteCount member:

    Te codebehind for the main window creates the ViewModel:public partial class MainWindow{ public MainWindow() { DataContext = new BadMainViewModelA(); InitializeComponent(); }}

    Common MistakesYou might notice the ViewModel type is called BadMainView-ModelA. his is because Im going to first look at a couple ofcommon mistakes relating to ViewModels. One common mistakeis to synchronously block on the operation, like so:

    public class BadMainViewModelA{ public BadMainViewModelA() { // BAD CODE!!! UrlByteCount =

    MyStaticService.CountBytesInUrlAsync("http://www.example.com").Result; }

    public int UrlByteCount { get; private set; }}

    Tis is a violation of the async guideline async all the way, butsometimes developers try this if they feel theyre out of options.If you execute that code, youll see it works, to a certain extent.Code that uses ask.Wait or ask.Result instead of await issynchronously blocking on that operation.

    Tere are a few problems with synchronous blocking. Te mostobvious is the code is now taking an asynchronous operation andblocking on it; by doing so, it loses all the benets of asynchronicity.If you execute the current code, youll see the application doesnothing for a few seconds, and then the UI window springs fullyformed into view with its results already populated. Te problemis the application is unresponsive, which is unacceptable for manymodern applications. Te example code has a deliberate delay toemphasize that unresponsiveness; in a real-world application, thisproblem might go unnoticed during development and show up onlyin unusual client scenarios (such as loss of network connectivity).

    Another problem with synchronous blocking is more subtle: Tecode is more brittle. My example service uses CongureAwait(false)

    properly, just as a service should. However, this is easy to forget,especially if you (or your coworkers) dont regularly use async.Consider what could happen over time as the service code is main-tained. A maintenance developer might forget a CongureAwait,and at that point the blocking of the UI thread would become adeadlock of the UI thread. (Tis is described in more detail in my

    previous article on async best practices.)OK, so you should use async all the way. However, many devel-

    opers proceed to the second faulty approach, illustrated in Figure 3.Again, if you execute this code, youll nd that it works. Te UI

    now shows immediately, with in the label for a few secondsbefore its updated with the correct value. Te UI is responsive, andeverything seems ne. However, the problem in this case is han-dling errors. With an async void method, any errors raised by theasynchronous operation will crash the application by default. Tis isanother situation thats easy to miss during development and showsup only in weird conditions on client devices. Even changing thecode in Figure 3from async void to async ask barely improves the

    application; all errors would be silently ignored, leaving the userwondering what happened. Neither method of handling errors isappropriate. And though its possible to deal with this by catchingexceptions from the asynchronous operation and updating otherdata-bound properties, that would result in a lot of tedious code.

    A Better ApproachIdeally, what I really want is a type just like ask with propertiesfor getting results or error details. Unfortunately, ask is notdata-binding friendly for two reasons: it doesnt implement INotify-PropertyChanged and its Result property is blocking. However, youcan dene a ask watcher of sorts, such as the type inFigure 4.

    using System.ComponentModel;using System.Runtime.CompilerServices;public sealed class BadMainViewModelB : INotifyPropertyChanged{ public BadMainViewModelB() { Initialize(); }// BAD CODE!!!

    private async void Initialize() {

    UrlByteCount = await MyStaticService.CountBytesInUrlAsync( "http://www.example.com"); }private int _urlByteCount;

    public int UrlByteCount { get { return _urlByteCount; } private set { _urlByteCount = value; OnPropertyChanged(); } }public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); }

    }

    Figure 3BadMainViewModelB.cs

  • 8/21/2019 MDN_1403DS

    25/108

    pu page. lem n s, , ; ersion page. lemen s, , ; ersion up page. lemen s, , ; ersii n up page. lemen s, , ; pa

    48 , ; ersion age.Elemen s, 0, 405 ;AddUP Version up2 page.Elements, 240, 405 ;AddUP VersionE up5 pa l. ll men s,, , ; thepage othedocument documen

    Rec ngl el nts,EA N 13Bar o e, x, y, 204, 99 ; Bar o ebar ode = new Ean13 123456789012, x, y+ 1 ; bar o . += - r e. e ymbolWid 2; elements.Add bar

    elem ne s,, JAN 13 B r ode,2 digitsupplement, x,y, 204,99 ; ar ode bar ode = new Ean1 up , x, + bar o e. += 4 - bar ode. et ymbolWidth 2; ele

    oat y){ dd ptionAndRect ngle(elements, EAN/JAN13 Bar Code, 5 digit supplement, x, y,204, 99); B rCode b r o e new 13Sup5(1234 678901212345, x, y+ 21); barCode.X +=(204

    onA( roup ele enm ts, floatx, fl ty) { AddCaptionAndRectangle(elements, UPC VersionA Bar Code,x, y 2, 04, 9 ; rB Code ar ode= n w UpcVersionA(12345678901, x,y +21); barCode.X+

    onA (p Gr pelements,, fl t , floaty) { AddCaptionAndRectangle(elements, UPCVersion E Bar Code, 2 digii su pleme , , y, 204, 99);BarCo ebar ode= new UpcVersionASup2(123456

    ode); private v idAddU C irs onASup5(Group elements, floatx, float y) { AddCaptionAndRectangle(ele ent , PC rsion EBar Code, 5 di it supplement,x, y, 204, 99);BarCodebarCode=

    bolWi th(dt )) / ;2 elements. d ( rba Code); }private void AddE NA 8(Group elements, float x, float y) { Ad ap ition nd ngle(ele ents,EAN/JA 8 Bar Co e, x, y, 204, 99); BarCode barCode =n

    g.Titll Open ile Dialo ; leDialog.Filter = obe PD file (*.pdf)|*.pdf|All Files(*.*)|*.*; if(file iial .l . ow iall () == Dialo Result.OK) { pdfViewer.OpenFile(fileDialog.FileName, ); } S ve

    ; a eFileDi loal g.Filter = oAd bePDF files (*.pdf)|*.pdf|AllFiles (.*)|*.*; if (saveFileDialog.Sho Di li lo = iiiai logRes llt . K) { pdf iewer.SaveAs(saveFile ii log.FileName ; if

    ; } els { M sse geBox.Sho ( lease opena file to print); } penFileDialog fileDialol = ew O nFile ialog(); file Dialog.Tiitle = OpenFile Dial ; filleDialog.InitialDir ct ry = @c: ; fileDl ia

    R uls t. K) { y amicPDFViewerClass test= n Dw yna icPDFVi erCr lass(); PD iPri ter p irii er test.O nFileFor ri ter l(fil Di log.FileName); rinter.PrintQ ii t(); } b

    G HC le g h= GCHandle.Alll oc(contents,GC andleType.Pinne ); IntPtr con IntPtr g h. ddrOfPin edObjec ()t ; df Viewer.O nBuffer

    e Elle ent:, , y);pageElements.Add(new Bookmark( ookmarked Text, ,+ y +20,p en Outline)); pa eElemen s.t dd (new Label(Thi text is bo k ar d ,. ,

    , o ta x, flo t y) {//Addsa circl to thepageEllem ntsAddCapti n nd ectangle(p g lel te s, Circle P ge Ele nt:, x, y); pa leElements..A new C

    ri a void dF rmatt dTextArea(Group pa Elemen s,floa x, oa y) /{ / d a rma edtext area o hepage lle ments stringfor a dHtml =< > i>Dynamic< D>P F ; Gen

    pportf r text at t ppears inthe ocument. o ha e + compll e c ntr l e paragra ph roperties: spacing b for , spacingafter, rst liine + indentation, left indentatiion, right ii nde atioi ,

    = imTi >font acf e, < on c lll rll =FF 00>col r, bb old, / > i>italic and underlinel o >< hisis a very imple HT

    er=\1\>100200 + 300400500600 o y>;C nv rsion.. onv r.ConvertHtmlString(s pll Htmll

    ath.Combine(GetPath(), LetterPortrait.p f)); printJ b.DocumentNam = LettL er Portrait; if(printJob.Printer.Color) p iiiini tJ . rintOption Co. lor = u ; ifi iprini ob.Printer. ollate) printJo P.. rint p ii

    i

    ,

    http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.com/http://www.dynamicpdf.c