Bending APIs to Your Will Using Windows Phone 8 Kamran Ayub (MDC 2013) [email protected] @kamranayub kamranicus.com Follow along: http://mdc.ilmservice.com/download
Play (too many) video games Watch (too many) TV shows Hang out with (just enough) friends Am getting married (thanks Cassie!) Other than developing software, I…
Started programming in 2001 Classic ASP , HTML & CSS (FrontPage) Moved onto ASP .NET 1.1 VB.NET, Web Forms, HTML & CSS (Server d) Spent some time freelancing PHP , MySQL, ASP .NET, C#, HTML & CSS (“hand-crafted”) Got a job in college PHP , MySQL, HTML & CSS (Actually OK) Got hired at General Mills (3 years ago) ASP .NET 4.0/4.5, ASP .NET MVC, C#, HTML & CSS Meanwhile, after hours… JavaScript frameworks, ASP .NET Web API, Windows Phone apps, Windows 8 apps, open source Where I’m Coming From
Underscore-KO Mashup library that adds Underscore.js functions to Knockout arrays Giantbomb-CSharp .NET API SDK for GiantBomb site .JSON Tiny dynamic JSON API to parse and create JSON Other random gists and scripts Other contributions github.com/kamranayub
I didn’t ask Is there a RESTful API for it? As long as there’s a programmatic way to access data on the site, REST or not, you can create a front-end for it. Also, it’s probably not really RESTful.
I didn’t ask Can I make money off it? Let the app speak for itself before trying to think of ways to make money off it. And whatever you do, provide a way for people to try before they buy or offer in-app upgrades.
I didn’t ask Is there a website someone else uses a lot? If you don’t use it regularly, chances are good you’ll miss what’s really important for the mobile experience.
Websites I use in a typical week Website Has a way to access data Website Has a way to access data StackOverflow Yes Mint No Facebook Yes Medium Sort of (Microformats) Feedly Yes GiantBomb Yes Amazon Yes Reddit Yes Gmail Yes GameTrailers Limited (RSS feeds) Forecast.io Yes Wikipedia Yes Tweetdeck (Twitter) Yes Codeplex Yes Github Yes Splitwise Yes MSDN No Springpad Yes Youtube Yes Foursquare Yes USAA No Steam Store Yes
Caliburn.Micro (or equivalent MVVM) MVVM framework to speed up development Microsoft.Bcl.Async Async/Await support, even for WP7.1+ Microsoft.Net.Http Easy-to-use lightweight async-compatible HttpClient Windows Phone Toolkit Provides tons of controls Modern UI Icons modernuiicons.com Essential Packages and Tools
GovTalk is a soon-to-be-released Windows Phone application that makes it easy to contact and learn about your congressional representatives. It is built on top of the public Sunlight Labs API. GovTalk Walkthrough
Model View View Model Model-View-ViewModel • State • Domain • Renders the interface to the user • Accepts input from the user • Logic for controlling the view • Transforms Model to View- friendly model (View Model) Services • Dependencies • Business logic • Encapsulate device features
MVVM Framework Use Caliburn to simplify your code when building apps Install Caliburn.Micro Nuget package This installs the required framework Install Caliburn.Micro.Start Nuget package This gets you started with using Caliburn Bonus: Install Caliburn.Micro.BindableAppBar to make it easier to create dynamic context-sensitive app bars Guess who made this?
Connecting to Sunlight Labs Wrap your connection-logic into an API client class Create a repository to manage working with the API client and any local storage solutions Register the two services with Caliburn Inject and consume the repository in your view models
API Client: Wrap the connection logic It’s easy to use the HttpClient to connect to an API Create a generic request helper to assist in sending requests
API Client: Generic request method (cont’d) If there is no response content, we’ll throw. Then, we deserialize the response content (using JSON.NET in this case) and returning the expected type. Gotcha: “Root Element” Example response from server { "legislator": { "first_name": "Kamran", "last_name": "Ayub" } }
Register with container Use the bootstrapper code and add your own services Your repository and client can be PerRequest but I’ve used Singleton for my app. Since the main page is a Panorama, I’ve also made that a Singleton as well. SettingsModel is used to store cacheable settings, so that’s a Singleton.
Dependency Injection Finally, inject your dependencies into your view model’s ctor In addition, you can inject other view models as well, either as an instance public MyRepsViewModel(SettingsModel settings) or a factory that generates new instances: public MyRepsViewModel(Func settingsFactory)
Feeding the Data Into the View Load the data when the view is activated or initialized Bind the data to an observable Display the data in the UI in a sexy fashion Cache the data
Representatives is a flat collection that I use for caching and storage. Expose public observable properties Due to differences in the API for WP7/WP8, you might need to use compile constants. LongListSelector differs for each platform.
Caliburn exposes any public properties on the view model for binding Bind to those properties in the XAML Caliburn let’s you use mock data in Visual Studio design view, very useful for UI design
Then, you need a parameterless constructor on your view model. Set up any fake data you want in the ctor. Use Caliburn’s InDesignMode to determine whether or not to set up your mocked data. You will see your fake data populated in the design-time view in Visual Studio, making it way easier to design! Design-Time Binding
How do you communicate between two view models? Pub/Sub mechanism Caliburn provides the IEventAggregator service View Model 1 View Model 2 IEventAggregator Publish Subscribe
Event Aggregator: Avoid Anti-Patterns Use consistent event interfaces (naming, structure, etc.) Avoid using event messaging for internal events (single VM) Be cognizant of other events triggering your events and plan accordingly Don’t modify the message contents (keep it immutable) Order of subscribers shouldn’t matter
Use a framework like Caliburn to provide structure Connect to your APIs intelligently and cache data Degrade gracefully (connection, platform, device features, etc.) Be respectful of your users time and constraints Creating compelling connected apps
What makes a great connected app? Offline Support Globalization & Localization Error Reporting & Logging Full API Support Extra App-Only Features Live Tiles Push Notifications Hardware Integration Features that make any app great Features that make a connected app great Queuing Write Methods Background Tasks Local Device Caching
MainViewModel.cs Supporting Deep Linking (“The Right Way”) Pinned Tile • User taps tile on start screen • URI MainViewModel.xaml ?LegislatorId=xxx Main Page •Caliburn injects query string values into view model •LegislatorId Navigate forward • Preserves back stack • Smooth UX
Extending the Navigation Service You can extend the navigation service easily using extension methods In a POST-Redirect-GET pattern, it works a little differently in a native app environment but the same logic applies. Redirect then raise a message:
OAuth Use the AsyncOAuth library (works well with HttpClient) Use DPAPI to store consumer access token and secret Use WebBrowser control to embed OAuth login page
Supporting Cancellation Create a new CancellationTokenSource for each request Pass the CancellationTokenSource.Token to your repository/client If you need to cancel, call CancellationTokenSource.Cancel() Handle the TaskCanceledException