Monday, October 1, 2012

Using Mobile Services in Windows 8 Managed Application (C# code)


Windows Azure Mobiles Services (WAMS) targets Windows 8 Applications in its first preview - a great starting point on the way to supporting multiple mobile platforms down the road. This post covers a few basics of using WAMS in managed code (C# or VB.NET) using C# examples. You could use VB.NET just as well. Some of this is already covered in tutorials but you might find this useful as a cheat sheet.

A Mobile Service created using WAMS has an http REST endpoint that can be used directly if you like. But  we  also ship an SDK (currently in MSI form) that elevates the experience quite a bit and bring it closer to the host language and platform. This post is about the SDK experience. If you haven't already completed the quick start and related tutorials, I strongly recommend you do those first. This post is intended to be complementary though I do repeat a few things to make the post a bit more self-contained.

Client

The main class is the MobileServicesClient - the go to class for all your needs. It takes two parameters:
  1. URL for the Mobile Service. This is globally unique (hence you need to pick a unique service name when you create one)
  2. App key: this identifies the app (since this is distributed with the app and viewable in fiddler or other browser dev tools, you could call it an "open secret"; i.e. it has identification value and no real security value)

public static MobileServiceClient client = new MobileServiceClient(appURL, appKey);

You start by getting a table proxy so that subsequent code can be strongly typed.

IMobileServiceTable<TodoItem> TodoTable = App.client.GetTable<TodoItem>();

Don't worry, just as in other LINQ incarnations, this table is just a proxy that knows how to perform CRUD type operations. The following statement does NOT retrieve the entire table down to the client. (In fact, for the app's good, we don't allow that even otherwise but more about it later).

The client also supports login in addition to CRUD (Create, Read, Update and Delete) operations.

Queries

In managed code, the query support is quite straightforward. It is basically the LINQ experience with support for a subset that roughly covers filtering, sorting and paging against a single collection (i.e. no joins, no groupby etc.).

Getting Results

There are a few options to get the results of a query that is executed asynchronously (hint: you can't just use regular ToList here; you need an awaitable task or something that can handle async ops)

// If you just want and IEnumerable. Returns an awaitable Task
var items0 = todoTable.ToEnumerableAsync();
// Friendly collection to iterate through
var items1 = todoTable.ToListAsync();
// More fancy data binding.
// ICollectionView, INotifyCollectionChanged, INotifyPropertyChanged and a bunch of other interfaces are implemented
MobileServiceCollectionView<TodoItem> items2 = todoTable.ToCollectionView();

For quick and dirty prototyping, I prefer to use MobileServiceCollectionView (MSCV). For more specific use; it is better to have your own custom implementation of ICV etc.

Filtering

MobileServiceTableQuery<TodoItem> query = todoTable.Where(todoItem => todoItem.Complete == false);
You could use the comprehension syntax if you prefer. It is just LINQ, though within limits of supported operators and member functions.
Lookup helps you get a single object.
// Singleton or null
var item0 = await todoTable.LookupAsync(id);
if (item0 != null)
{
    // For illustrative purposes only
    MessageDialog md = new MessageDialog(item0.Text);
    var ignoreAsyncResult = md.ShowAsync();
}

Sorting

As in case of filtering, you can use the standard LINQ operators with lambda or comprehension syntax:
var query = todoTable.OrderBy(t => t.Text);

In addition, you can also use other operators like ThenBy, OrderByDescending etc.

Paging

For mobile apps, data is often bound to a UI so it is often best retrieved a page at a time. On slower networks, even data retrieved for other purposes (i.e. not for directly displaying in a UI) should be limited through paging. Paging relies on LINQ Skip and Take operators.
// First page
var query = todoTable.OrderBy(t => t.Text).Take(page_size);
// For (n+1)th page
var query = todoTable.OrderBy(t => t.Text).Skip(n*page_size).Take(page_size);

Mobile Services runtime (server-side) provides paging by default by restricting the results to 50 objects. This is usually appropriate for most UI binding scenarios. You can override that by applying Take(n) where n can be any number from 1 to 1000.

There is also a way to get the total count of all objects matching your query (not just the first page). I will cover that in a separate post later.

CUD
Create, Update and Delete operations are quite straightforward.

    // Insert a new record
    TodoItem newItem = new TodoItem { Text = "Complete C# Client blog post", Complete = false };
    await todoTable.InsertAsync(newItem);

    // Update a record
    newItem.Complete = true;
    await todoTable.UpdateAsync(newItem);

    // Delete a record
    await todoTable.DeleteAsync(newItem);

Insert operation performs dynamic schematization. You don't need to go through the ceremony of creating a table with typed columns etc. Mobile Services run-time looks at the properties in the JSON payload and adds eponymous column(s) if they are not already present. It looks at the value of the property to infer the type. Of course, because the base types in JavaScript (which is what is used for server scripts and underlies JSON) are fairly simple, the list of types is much smaller than that in .NET or SQL. Here is a quick table that describes the types currently used.

JSON Value
T-SQL Type
Numeric values (integer, decimal, floating point)
Float(53)
Boolean
Bit
DateTime
DateTimeOffset(3)
String
Nvarchar(max)

Likewise, update operation can also perform dynamic schematization if necessary.

Typically you want dynamic schematization when you are developing your app for rapid turnaround and changes. When you deploy, it is usually a good idea to "lock down" the schema by turning off dynamic schematization so users of your app can't accidentally or maliciously expand the schema. Mobile Service developers can turn off dynamic schematization in the portal ("CONFIGURE" tab).

For the delete operation, the only property on newItem object that matters is the ID assigned by Mobile Service when the object was created in the table.

Untyped Usage
The C# client is primarily designed for strongly typed scenarios. However, sometimes a more loosely typed experience is convenient (e.g. objects with open schema). That is enabled as follows. In queries, you lose LINQ and you have to dropped down to effectively the wire-format.

    // Get an untyped table reference
    IMobileServiceTable untypedTodoTable = App.MobileService.GetTable("TodoItems");

    // Lookup untyped data using odata
    IJsonValue untypedItems = await untypedTodoTable.ReadAsync("$filter=complete eq 0&$orderby=text");

You get back JSON value that you can use like a property bag.

Login
I strongly recommend going through the tutorial on our dev center to understand authentication and users. This is just for completing the cheat sheet:
    // Log in
    MobileServiceUser user = await App.MobileService.LoginAsync(windowsLiveToken);

Thursday, December 2, 2010

Learning about WCF/Silverlight and WCF RIA Services via videos

Some folks prefer videos to text material. Others find them complementary. Either way, here are some videos about WCF and WCF RIA Services in Silverlight. I am sure there are more created by community – feel free to add links. Many, if not most of the videos are based on extensive preparation and so they are a bit more tailored for learning than a run of the mille blog post.

Short intro from Silverlight 4 launch

Scott Guthrie’s keynote. A short ten minute intro to RIA Services with client emphasis is from 28:00 onwards

Silverlight TV / Channel 9 episodes

Yavor walks through verification and troubleshooting steps for accessing a WCF service form Silverlight.

Tomek covers duplex communication in WCF – Silverlight using a chat application example.

Saurabh covers the steps to address the common support issue of RIA app deployment.

Deepesh covers top questions including POCO, client-side computed properties, access control and Windows auth

Dinesh covers POCO, code-gen rules, association and composition, using nhibernate etc

Deepesh covers the use of SOAP/JSON endpoints for other clients including Windows Phone 7 client. Also covers use of OData endpoint with Excel.


Kyle covers validation in depeth

Nikhil and Dinesh about RIA Services evolution, purpose, favorite features etc

John Papa talks to Jeff Handley about how community is involved in WCF RIA Services

Jeff, Dinesh, Deepesh talk about how RIA Services V1 was developed. What it is about etc.

How RIA Services component is developed, validation etc.
  
Full conference talks

Deepesh shares a comprehensive list of tips at TechEd 2010

Yavor’s in-depth look at WCF/Silverlight

Nikhil shows how to build a RIA Services app the right way without sweat at MIX 2010

Nikhil’s JAOO talk about RIA Services – Sept 2010

Two part coverage of WCF RIA Services at PDC 2009
Introductory talk by Brad Abrams – covers overview, drag drop experience and overall productivity

Dinesh provides an under-the-hood look at how RIA Services works and also covers key tips for building effective RIA applications

Training / external videos



Tuesday, November 2, 2010

Complex types in RIA Services: base types or entities?

When we designed complex types for WCF RIA Services V1 SP1, we had a hot debate. Are complex types like base types or entities? Well, they are a bit of both.

They are like base types in the sense:
  1. They are structured values; not objects with identity
  2. They can be used for entity members or DomainService method parameters
  3. There is no inheritance or association (inbound or outbound) support
They are like entities in the sense
  1. They are code-gen'ed
  2. They are deeply change tracked, validated (with error reporting) when used in an entity
They are definitely not intended to be substituted for entities. They are not meant to replace composition where the composed object is an entity.

Samples of intended use:
Customer.Address where address does not have an identity of its own
Shape.Coordinate where coordinate is used like a value (no associations etc)

Samples of unintended use:
In place of composition -
Order.OrderDetail // OrderDetail if captured in a separate relational entity likely has its own ID and associations
For many-to-many link entity/table
Course.Registration or Student.Registration // another entity with its ID

In this round, we didn't really get a chance to provide a mechanism to use a complex types like a base-type - with essentially a portable assembly across Silverlight and .NET. That was a scoping decision based on priority feedback from a few MVPs we regularly talk to.

For more about the feature use and all the bells and whistles see Mathew's detailed blog post.

What is your scenario for complex types? Do the beta bits releases at PDC work well for your scenarios?

Thanks.
Dinesh

Wednesday, October 27, 2010

Journey from RIA Services V1 to V1 SP1 Beta

Finally on the eve of PDC 2010, we get to share our latest bits with the community. Jeff has done a great job of covering the details of what's in so I won't repeat that here. Just check his latest post for that and also Tomek's posts that cover a broader vista of WCF technologies on tap for PDC. Instead, I will briefly cover how it shaped up.

Like many other V1s, WCF RIA Services V1 was done under intense time pressure and locked to Silverlight 4 Tools schedule. In hindsight too, that was the right thing to do as it allowed us to get a reasonably feature-full and capable package in users' hands. The response was very gratifying and on occasions, I was pleasantly surprised by what folks in the community were able to build with our bits. We as a team were also glad to see strong community involvement - when folks showed appreciation and when those in the know took us to task for missing capabilities or plain bugs or missing info (sadly most frequent of the three). There were many who spent so many of their hours advising us - Colin Blair, David Yack, Ben Hayat, Fredrik Normen, Dan Wahlin, Bill Burrows, Billy Hollis and many others outside Microsoft. Equally impressive were those who weren't directly on the product team but every bit a part of it with their contributions - John Papa, Pete Brown, Tim Heuer and many others.

SP1 is our attempt to give back to the community with a relatively quick turnaround - in about 5 months. Typically Service Packs (SP) are all about bug fixes and related quality improvements. This one is a bit more than that.

There were clear baseline capabilities that we wanted to cover in V1 but just couldn't. That was the price to pay for shipping - I guess well worth it. But we wanted to cover those soon. First came the bugs that had to be postponed because they didn't meet the high bar while locking down V1 RTW. So did a bunch of infrastructure and test improvements to make us more efficient and pay down debt. Then we were able to get to key items like "shared entities", complex types, ICollectionViewFactory and T4.

For this post, I will just briefly talk about shared entities - not being able to share the same entity type (say Employee) across two different DomainService types (say PurchaseOrderService and EmployeeInfoService) was a problem for those building apps with multiple DomainServices. Data models often have "spiders". The entity at the center of the spider is often involved in multiple submodels. The object model simply reflects that. Now you can do that without resorting to workarounds.

Doing that feature required some intense discussions about the approaches - each DomainService gets to "shape" the code-gen'ed entity in the client project. Do we take the intersection or the union? If one DomainService adds a named update method, how do you deal with the corresponding member on the entity in a different DomainService? What about associations that are different in the two DomainServices? After huddling with our "advisors" from the community, we settled on the union approach and the feature was on track. The usual design, implement, stabilize, meet all quality gates were done and we were close to PDC lockdown date.

Such was the journey. Maybe I will cover some bugs in the next installment. If you would like to see anything specific covered, please let me know about that as well.

Until then, please try the bits and keep the feedback flowing - on forums, blogs, twitter ...

First post since move

Here is the starter post to wave my flag. My previous blog entries were at
http://blogs.msdn.com/dinesh.kulkarni

Briefly, I have worked on LINQ / C# and WCF RIA Services.