Top Banner
Lessons From The Lessons From The Trenches Trenches Engineering great AJAX Engineering great AJAX experiences experiences Scott Isaacs Scott Isaacs Architect Architect Windows Live Frameworks Windows Live Frameworks Microsoft Corporation Microsoft Corporation NGW020
38

Lessons from the Trenches: Engineering Great AJAX Experiences

Jan 15, 2015

Download

Documents

goodfriday

Explore the challenges and lessons learned developing the Windows Live and Gadgets Web client frameworks powering Windows Live, Hotmail (Kahuna beta), Spaces, and more. This technical talk presents design and architectural considerations for building interactive AJAX-like sites. See how componentization, network management, accessibility, page composition, and more impact the design and engineering of your Web application.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Lessons from the Trenches: Engineering Great AJAX Experiences

Lessons From The TrenchesLessons From The TrenchesEngineering great AJAX experiencesEngineering great AJAX experiences

Scott IsaacsScott IsaacsArchitectArchitectWindows Live FrameworksWindows Live FrameworksMicrosoft CorporationMicrosoft Corporation

NGW020

Page 2: Lessons from the Trenches: Engineering Great AJAX Experiences

AgendaAgenda

Rethinking Web ApplicationsRethinking Web Applications

"Remixing" on Windows Live "Remixing" on Windows Live Gadgets, gadgets, gadgets!Gadgets, gadgets, gadgets!

What did we learn?What did we learn?Component modelsComponent models

Network ManagementNetwork Management

More…More…

Page 3: Lessons from the Trenches: Engineering Great AJAX Experiences

So What Is AJAX?So What Is AJAX?

Weather Service

function DoAdd(strLoc){ Weather.Request(strLoc,onReceive)}

function onReceive(obWeatherData){ ProcessWeather(objWeatherData)}

Page 4: Lessons from the Trenches: Engineering Great AJAX Experiences

AJAX – The DetailsAJAX – The Details

Describes a simple development patternDescribes a simple development patternAsynchronously request data from the serverAsynchronously request data from the server

Process the ResultProcess the Result

Update the PageUpdate the Page

Technology has been around for many yearsTechnology has been around for many years

Very good for improving form interactionsVery good for improving form interactions

Usually insufficient by itself for building Usually insufficient by itself for building applicationsapplications

Ajax is one tool (pattern) of many for building Ajax is one tool (pattern) of many for building rich experiencesrich experiences

Page 5: Lessons from the Trenches: Engineering Great AJAX Experiences

What Is A Mash-Up?What Is A Mash-Up?

Web applications that consumes Web applications that consumes ("remixes") content and experience from ("remixes") content and experience from different sources and aggregates them to different sources and aggregates them to

create a new applicationcreate a new application

Page 6: Lessons from the Trenches: Engineering Great AJAX Experiences

Remixing The WebRemixing The Web

What is the real web application What is the real web application revolution?revolution?

I don't believe it is just AjaxI don't believe it is just Ajax

Where RSS democratized and syndicated Where RSS democratized and syndicated content, mash-up patterns will content, mash-up patterns will democratize and syndicate experiences democratize and syndicate experiences and ease service integrationand ease service integration

You can extend your reach by You can extend your reach by integrating with the rest of the webintegrating with the rest of the web

E.g., Windows Live Virtual Earth, "Blog E.g., Windows Live Virtual Earth, "Blog This" page add-ons, etcThis" page add-ons, etc

Page 7: Lessons from the Trenches: Engineering Great AJAX Experiences

Rethinking The WebRethinking The WebWhat if everything was a mash-up?What if everything was a mash-up?

Mashing up as an architectural patternMashing up as an architectural patternMore Efficient DevelopmentMore Efficient Development

Requires ComponentizationRequires ComponentizationWeb Pages are collections of ComponentsWeb Pages are collections of Components

Better caching and reuse of resourcesBetter caching and reuse of resources

Eliminate "spaghetti" ad-hoc HTML-codingEliminate "spaghetti" ad-hoc HTML-coding

Leverage your investmentsLeverage your investmentsReuse components across your productReuse components across your product

Reuse your components across the webReuse your components across the web

The opportunity to be remixedThe opportunity to be remixed

Share more than just "services"Share more than just "services"Provide default and customizable experiencesProvide default and customizable experiences

Page 8: Lessons from the Trenches: Engineering Great AJAX Experiences

Remixing Windows LiveRemixing Windows Live

Windows Live properties are mash-upsWindows Live properties are mash-upshttp://mail.live.com (Hotmail Beta)http://mail.live.com (Hotmail Beta)

http://www.live.com http://www.live.com

Page 9: Lessons from the Trenches: Engineering Great AJAX Experiences

Why The Mash-Up Why The Mash-Up Philosophy?Philosophy?

More efficient development processMore efficient development processWe can share development resourcesWe can share development resources

We can be more robustWe can be more robust

We can quickly integrate services across We can quickly integrate services across properties without heavy server liftingproperties without heavy server lifting

We can provide a consistent experienceWe can provide a consistent experience

We can scale betterWe can scale better

Most important, we can offer better and more Most important, we can offer better and more consistent customer experiences and valueconsistent customer experiences and value

We dogfood one pattern (gadgets) for We dogfood one pattern (gadgets) for building and extending our propertiesbuilding and extending our properties

Page 10: Lessons from the Trenches: Engineering Great AJAX Experiences

The Gadget EcosystemThe Gadget Ecosystem

At the core, all UI components are GadgetsAt the core, all UI components are Gadgets

Third-party developers canThird-party developers canExtend Windows Live home pageExtend Windows Live home page

In the futureIn the futureExtend other web experiences such as SpacesExtend other web experiences such as Spaces

Host Windows Live Gadgets on their own site Host Windows Live Gadgets on their own site

Extend Windows with Gadgets via the SidebarExtend Windows with Gadgets via the Sidebar

Learning more…Learning more…See See http://http://www.microsoftgadgets.comwww.microsoftgadgets.com

Supported by ASP.Net Codename “Atlas”Supported by ASP.Net Codename “Atlas”

Page 11: Lessons from the Trenches: Engineering Great AJAX Experiences

Let’s start digging in…Let’s start digging in…

Page 12: Lessons from the Trenches: Engineering Great AJAX Experiences

So what did we learn?So what did we learn?

Our mash-up architecture taught us a Our mash-up architecture taught us a lot about building very rich interactive lot about building very rich interactive applicationsapplicationsWe needed to evolve the AJAX pattern We needed to evolve the AJAX pattern to handle “real-world” issuesto handle “real-world” issuesWe desired one “platform” to enable We desired one “platform” to enable modern development and reusemodern development and reuseWe created patterns and approaches to We created patterns and approaches to work around the limitations of the host work around the limitations of the host environment (the browser)environment (the browser)… … and we are still learning…and we are still learning…

Page 13: Lessons from the Trenches: Engineering Great AJAX Experiences

Building Web ApplicationsBuilding Web ApplicationsAJAX - The MythAJAX - The Myth

With Ajax, my application will With Ajax, my application will scale better, scale better, run faster, run faster,

and offer a better user experienceand offer a better user experience

Page 14: Lessons from the Trenches: Engineering Great AJAX Experiences

Evolving The AJAX PatternEvolving The AJAX Pattern

We are solving challenges for building interactive We are solving challenges for building interactive web applicationsweb applications

Defined a set of programming patterns to enable interactive Defined a set of programming patterns to enable interactive web-sitesweb-sites

Windows Live Architecture enablesWindows Live Architecture enablesClient-Side Page CompositionClient-Side Page CompositionModern Development PatternsModern Development PatternsComponent ModelComponent ModelNetwork ManagementNetwork ManagementResource DeploymentResource DeploymentProxying, Caching, and ScalabilityProxying, Caching, and ScalabilityThemes and consistent experienceThemes and consistent experienceCross-Browser equalizerCross-Browser equalizer

So what does it take to build a robust rich web So what does it take to build a robust rich web application?application?

Page 15: Lessons from the Trenches: Engineering Great AJAX Experiences

The Application “Container”The Application “Container”

Server composes pageServer composes pageComponents directly embedded as page loadsComponents directly embedded as page loads

E.g., Adding/ Removing components reloads the pageE.g., Adding/ Removing components reloads the page

Initially easier to implement (content is flowed into the document)Initially easier to implement (content is flowed into the document)

Intelligent Caching is more difficult – page size grows quicklyIntelligent Caching is more difficult – page size grows quickly

All components impact page loadAll components impact page load

Client composes page Client composes page Components dynamically included on the pageComponents dynamically included on the page

Uses frameworks to deploy and inject componentsUses frameworks to deploy and inject components

Highly leverages caching of static resources – better scalabilityHighly leverages caching of static resources – better scalability

Page composition can be “staged” and prioritized Page composition can be “staged” and prioritized

Easier “mash-up” integration but harder application developmentEasier “mash-up” integration but harder application development

Scenario (not technology) should drive the chosen approachScenario (not technology) should drive the chosen approach

Page 16: Lessons from the Trenches: Engineering Great AJAX Experiences

Client CompositionClient Composition

Page 17: Lessons from the Trenches: Engineering Great AJAX Experiences

Modern Development Modern Development PatternsPatterns

Apply OO principals to web developmentApply OO principals to web developmentShared methodology with AtlasShared methodology with Atlas

Namespaces, Encapsulation, Inheritance, Object LifecycleNamespaces, Encapsulation, Inheritance, Object LifecycleregisterNamespace("ScottIsaacs");registerNamespace("ScottIsaacs");ScottIsaacs.MyClass = function()ScottIsaacs.MyClass = function(){{

this.initialize = function() {};this.initialize = function() {};this.dispose = function() {};this.dispose = function() {};

}}

Application defines an object’s lifecycle, not the pageApplication defines an object’s lifecycle, not the page

Separate semantics, presentation, and behaviorSeparate semantics, presentation, and behaviorBuild and program against objects, not structureBuild and program against objects, not structure

Yields more stable, maintainable systemYields more stable, maintainable system

Page 18: Lessons from the Trenches: Engineering Great AJAX Experiences

Gadget ChallengesGadget Challenges

How do you build and integrate How do you build and integrate components (gadgets)?components (gadgets)?

Integrating components without collisionsIntegrating components without collisions

Consistent theme across componentsConsistent theme across components

Applying behaviors to HTML structureApplying behaviors to HTML structure

Enabling Asynchronous Client-Side Page Enabling Asynchronous Client-Side Page Composition (Deployment)Composition (Deployment)

Security and IsolationSecurity and Isolation

Page 19: Lessons from the Trenches: Engineering Great AJAX Experiences

Gadget “Patterns”Gadget “Patterns”

Minimal RequirementsMinimal RequirementsEncapsulation Patterns (e.g., we use JavaScript Closures) Encapsulation Patterns (e.g., we use JavaScript Closures)

Patterns to manage object lifecyclePatterns to manage object lifecycle

Separate Semantics, Presentation, and BehaviorSeparate Semantics, Presentation, and Behavior

Advanced RequirementsAdvanced RequirementsPatterns to enable asynchronous deploymentPatterns to enable asynchronous deployment

Patterns to enable asynchronous component Patterns to enable asynchronous component communicationcommunication

Patterns to "infect" components with the appropriate themePatterns to "infect" components with the appropriate theme

Patterns to scope CSS layout to component typesPatterns to scope CSS layout to component types

Patterns to provide “Process Isolation”Patterns to provide “Process Isolation”

Page 20: Lessons from the Trenches: Engineering Great AJAX Experiences

Defining A GadgetDefining A Gadget

Binds To

Renders

Gadget

function Live.Weather(el,args){ Live.Weather.initializeBase(thi this.initialize = function(p_own { ….

.Live_Weather {margin:2px}

.Live_Weather input (width:50%;…

HTML…<div class=“weather”></div>…

Page 21: Lessons from the Trenches: Engineering Great AJAX Experiences

Live Clipboard DemoLive Clipboard Demo

A “Clipboard” for the WebA “Clipboard” for the WebEnables copying microformats between web pages and Enables copying microformats between web pages and applicationsapplications

Extending Existing ContentExtending Existing ContentAutomatically bind behavior via CSS to elements (e.g., Automatically bind behavior via CSS to elements (e.g., microformats) on your pagemicroformats) on your page

Our future approach to integrating Live ClipboardOur future approach to integrating Live Clipboard

Becomes a “Service” we can apply to GadgetsBecomes a “Service” we can apply to Gadgets

Demo…Demo…

More About Live ClipboardMore About Live ClipboardRead http://spaces.msn.com/rayozzieRead http://spaces.msn.com/rayozzie

Attend “Wiring the Web” Wed @ 8:30amAttend “Wiring the Web” Wed @ 8:30am

Page 22: Lessons from the Trenches: Engineering Great AJAX Experiences

XML Proxying And ScalabilityXML Proxying And Scalability

ScenarioScenarioHow do you consume arbitrary RSS feeds?How do you consume arbitrary RSS feeds?You need to proxy the requests through your serverYou need to proxy the requests through your serverConsider the scalability implications (intelligently cache remote Consider the scalability implications (intelligently cache remote data, etc.)data, etc.)

Browser Sandbox ProblemBrowser Sandbox ProblemThe client cannot consume XML data from other domains The client cannot consume XML data from other domains How do you get the data?How do you get the data?

So how do maps works and why they are unique?So how do maps works and why they are unique?They are a set of images with algorithmically determines URLsThey are a set of images with algorithmically determines URLsIt would be difficult to consume a geo-location service via the clientIt would be difficult to consume a geo-location service via the clientIntegrating disparate services and personal data is the next Integrating disparate services and personal data is the next challengechallengeThe mapping components (e.g., Virtual Earth) are not typical AJAX The mapping components (e.g., Virtual Earth) are not typical AJAX (no XML)(no XML)

Some creative solutions using dynamic scripts instead of xmlSome creative solutions using dynamic scripts instead of xml

Page 23: Lessons from the Trenches: Engineering Great AJAX Experiences

Web Service IntegrationWeb Service Integration

Do not want to continually parse XMLDo not want to continually parse XMLDesire a more natural and efficient approachDesire a more natural and efficient approach

Web Services generate JavaScript proxies:Web Services generate JavaScript proxies:WeatherService.requestWeatherReport(strLocatioWeatherService.requestWeatherReport(strLocation,onReceipt)n,onReceipt)Use generic format for transport (e.g., JSON)Use generic format for transport (e.g., JSON)Incoming requests marshaled to native server Incoming requests marshaled to native server format and outgoing responses to client formatformat and outgoing responses to client format

Use xmlHttpRequest to access the network, Use xmlHttpRequest to access the network, but the wire format is transparent to the but the wire format is transparent to the applicationapplication

Use raw XML for "documents" (e.g., RSS)Use raw XML for "documents" (e.g., RSS)

Page 24: Lessons from the Trenches: Engineering Great AJAX Experiences

Optimizing The NetworkOptimizing The Network

AJAX-style applications can become AJAX-style applications can become very chattyvery chatty

E.g., fetch stock quotes, fetch weather, E.g., fetch stock quotes, fetch weather, fetch top articles, etc to render the pagefetch top articles, etc to render the page

Look for caching opportunitiesLook for caching opportunities

Look for opportunities to batch requests Look for opportunities to batch requests (especially requests that may share (especially requests that may share similar expensive upfront processing)similar expensive upfront processing)

Page 25: Lessons from the Trenches: Engineering Great AJAX Experiences

Be Wary Of SecurityBe Wary Of Security

Increased attack vectorsIncreased attack vectorsTraditionally pages were “rendered” entirely on the server – Traditionally pages were “rendered” entirely on the server – no direct client access to the underlying datano direct client access to the underlying data

With AJAX, data exposed directly via servicesWith AJAX, data exposed directly via services

AJAX and Mash-ups can increase likelihood of intentional AJAX and Mash-ups can increase likelihood of intentional and unintentional DOS attacksand unintentional DOS attacks

"Bad" code hitting your service"Bad" code hitting your service

Unintended repurposing of your servicesUnintended repurposing of your services

Mash-up Code SharingMash-up Code SharingYou must trust the code you consume or you must create a You must trust the code you consume or you must create a sandboxsandbox around the code around the code

Be careful referencing "untrusted" third-party scriptsBe careful referencing "untrusted" third-party scripts

Page 26: Lessons from the Trenches: Engineering Great AJAX Experiences

Advanced Network PatternsAdvanced Network Patterns

While AJAX prescribes a request-response pattern, it does not While AJAX prescribes a request-response pattern, it does not prescribe how to efficiently manage the networkprescribe how to efficiently manage the network

Before AJAXBefore AJAXWeb Page Model offers default connection managementWeb Page Model offers default connection management

Connections severed as you navigateConnections severed as you navigate

Failures were apparent via 404 errorsFailures were apparent via 404 errors

Requests were all equal (typically preloading images – order was not Requests were all equal (typically preloading images – order was not important)important)

Typically limited amount of scriptTypically limited amount of script

With AJAXWith AJAXMust be more aware of the unreliable networkMust be more aware of the unreliable network

Failures and users leaving the page before an operation completesFailures and users leaving the page before an operation completes

Some requests are relevant to specific contextsSome requests are relevant to specific contexts

Some requests are more important than others Some requests are more important than others (delete mail more important than preloading an image)(delete mail more important than preloading an image)

Potentially extensively more scriptPotentially extensively more script

How do you mitigate limited bandwidth and connections and How do you mitigate limited bandwidth and connections and proactively control the network in your web application?proactively control the network in your web application?

Page 27: Lessons from the Trenches: Engineering Great AJAX Experiences

Network ConstraintsNetwork Constraints

Browser offers no "reliable" transport Browser offers no "reliable" transport for network operationsfor network operations

Browser uses at most 2 simultaneous Browser uses at most 2 simultaneous connections per domainconnections per domain

Browser offers no built-in facility to Browser offers no built-in facility to interact with the network stackinteract with the network stack

Page 28: Lessons from the Trenches: Engineering Great AJAX Experiences

The Unreliable NetworkThe Unreliable Network

With AJAX, how do you guarantee "integrity" of the request?With AJAX, how do you guarantee "integrity" of the request?Most Web Applications incorrectly "assume" successMost Web Applications incorrectly "assume" success

For example, AJAX Shopping CartFor example, AJAX Shopping CartUser clicks buy and then quickly leaves the page. Did the order go User clicks buy and then quickly leaves the page. Did the order go through?through?

User clicks buy, switches views on the page, and the order fails. User clicks buy, switches views on the page, and the order fails. How do you notify the user?How do you notify the user?

Designing proper feedback is essentialDesigning proper feedback is essentialDefine a standard UI feedback metaphor and stick to itDefine a standard UI feedback metaphor and stick to it

Hotmail lets you know when it is "working…“Hotmail lets you know when it is "working…“

In IE, when integrity is required, you can ask the user to stay on In IE, when integrity is required, you can ask the user to stay on the page until an operation completes (but you can't force them)the page until an operation completes (but you can't force them)

Page 29: Lessons from the Trenches: Engineering Great AJAX Experiences

Emulating The Web ModelEmulating The Web Model

ScenarioScenarioBuild an application with multiple viewsBuild an application with multiple viewse.g., Inbox, Calendar, and Contactse.g., Inbox, Calendar, and Contacts

The first view is loadingThe first view is loading

User quickly switches to another view User quickly switches to another view before data completely loadsbefore data completely loads

Second view requests dataSecond view requests data

What happens?What happens?

Quick Demonstration…Quick Demonstration…

Page 30: Lessons from the Trenches: Engineering Great AJAX Experiences

Prioritizing Network Prioritizing Network RequestsRequests

AJAX ScenarioAJAX ScenarioYour page is preloading imagesYour page is preloading images

User clicks “Buy It" from your AJAX cart User clicks “Buy It" from your AJAX cart

When does the order request happen?When does the order request happen?

Proactively manage the network stackProactively manage the network stack

Page 31: Lessons from the Trenches: Engineering Great AJAX Experiences

Code/Resource DeploymentCode/Resource Deployment

More Interactivity = More Code = Slower SiteMore Interactivity = More Code = Slower SiteHow do you build sites with lots of componentsHow do you build sites with lots of componentsHow do you build a "portal" where the user controls the scope How do you build a "portal" where the user controls the scope of the applicationof the applicationHow do you efficiently deploy the necessary code and How do you efficiently deploy the necessary code and resources?resources?

Understand how the browser worksUnderstand how the browser worksScripts included on the page block and load one at a timeScripts included on the page block and load one at a timeLarge number of script blocks can greatly stall loadingLarge number of script blocks can greatly stall loading

System for deploying codeSystem for deploying codePatterns allow component resources to load in any orderPatterns allow component resources to load in any orderDeployed code asynchronously leveraging all available Deployed code asynchronously leveraging all available connectionsconnectionsPrioritize the loading of componentsPrioritize the loading of componentsNever expire static content (change the URL to break the cache)Never expire static content (change the URL to break the cache)

Page 32: Lessons from the Trenches: Engineering Great AJAX Experiences

X-Browser DevelopmentX-Browser Development

Minimize browser specific code in the Minimize browser specific code in the business logicbusiness logic

Abstract and centralize API differencesAbstract and centralize API differencesWe extend Firefox and Opera DOM to be We extend Firefox and Opera DOM to be compatible with IEcompatible with IE

CSS Differences – Avoid HacksCSS Differences – Avoid HacksWe classify and override via standard We classify and override via standard selectorsselectors<HTML class="Mozilla M1 D5 Windows"><HTML class="Mozilla M1 D5 Windows">Body {margin:10px}Body {margin:10px}.Mozilla Body {margin:5px} /* Override Mozilla */.Mozilla Body {margin:5px} /* Override Mozilla */

Page 33: Lessons from the Trenches: Engineering Great AJAX Experiences

The Remix ExperienceThe Remix Experience

How do you maintain consistency?How do you maintain consistency?

A critical issue as remixing growsA critical issue as remixing growsHow do you reflect your sites look and feel over How do you reflect your sites look and feel over third-party components?third-party components?

How do third-party components build CSS that How do third-party components build CSS that does not impact the sites intent?does not impact the sites intent?

Prescribed patterns to scope CSS to your Prescribed patterns to scope CSS to your componentcomponent

Your unique JavaScript class can serve as an Your unique JavaScript class can serve as an identifier to scope your stylesidentifier to scope your styles

Think how ambient themes "infect" Think how ambient themes "infect" componentscomponents

Page 34: Lessons from the Trenches: Engineering Great AJAX Experiences

Back Button And Back Button And AddressabilityAddressability

Users expect the web to workUsers expect the web to workDemo: MSN Spaces, Windows LiveDemo: MSN Spaces, Windows Live

Travelog (History stack) is hard Travelog (History stack) is hard Requires “hacks” to enable back-buttonRequires “hacks” to enable back-button

Need to decide what is a navigation (add to Need to decide what is a navigation (add to history) versus an actionhistory) versus an action

In some cases, a better experience may be In some cases, a better experience may be achieved by actually navigating and reloading achieved by actually navigating and reloading the pagethe page

URL Addressability Challenge, FavoritesURL Addressability Challenge, FavoritesShort Demo: Windows Live LocalShort Demo: Windows Live Local

Page 35: Lessons from the Trenches: Engineering Great AJAX Experiences

AccessibilityAccessibility

Web Accessibility is challengingWeb Accessibility is challenging

HTML AccessibilityHTML AccessibilityAlways use structural semantics to establish Always use structural semantics to establish “role”“role”

E.g., HE.g., Hnn, Label, TH (table headers), lists, etc., Label, TH (table headers), lists, etc.

DHTML “Effects” (Synchronous actions)DHTML “Effects” (Synchronous actions)Use “focusable” elements (e.g, hyperlinks)Use “focusable” elements (e.g, hyperlinks)

Dynamically display content in contextDynamically display content in context

AJAX (Asynchronous actions)AJAX (Asynchronous actions)Update in context then notify accessibility tool Update in context then notify accessibility tool that page is updatedthat page is updated

E.g., navigate a hidden iframeE.g., navigate a hidden iframe

Page 36: Lessons from the Trenches: Engineering Great AJAX Experiences

Building Web ApplicationsBuilding Web Applications

Conceptualize your application as a Mash-UpConceptualize your application as a Mash-UpPut "Engineering" into your clientPut "Engineering" into your clientFlesh out the intended scenarios and application Flesh out the intended scenarios and application flowflowAvoid (or minimize) breaking the Web ModelAvoid (or minimize) breaking the Web Model

To learn more on Microsoft’s investments in To learn more on Microsoft’s investments in this areathis area

Explore Microsoft Gadgets (Explore Microsoft Gadgets (http://http://www.microsoftgadgets.comwww.microsoftgadgets.com))Explore the Live ClipboardExplore the Live ClipboardDownload the latest Atlas CTP (http://atlas.asp.net)Download the latest Atlas CTP (http://atlas.asp.net)

Invest wisely…Invest wisely…Invest smartly and don't lose site of your customerInvest smartly and don't lose site of your customerIts your customer, not the technology you apply, Its your customer, not the technology you apply, that mattersthat matters

Page 37: Lessons from the Trenches: Engineering Great AJAX Experiences

QuestionsQuestions

Page 38: Lessons from the Trenches: Engineering Great AJAX Experiences

© 2006 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.