- Aug 09, 2010 at 2:36 PM
- Shawn Wildermuth
- 29 Comments
While I was giving my OData talk, someone asked about consuming OData on the WP7 phone. I had done this on the CTP earlier, but hadn't tried it during the beta. So I figured I'd look into it today. While this is still pretty easy to do, the tooling still isn't in place. This means that you can't simply do an "Add Service Reference" to a Windows Phone 7 project. Instead you have to follow these steps:
- Download the Windows Phone 7 OData Library here.
- Unzip the Windows Phone 7 OData Library to get access to the reference.
- In your project, add a reference to the System.Data.Services.Client.dll assembly from the .zip file.
- Create the proxy classes by using the .NET 4.0's DataSvcUtil.exe (located in the %windir%\Microsoft.NET\Framework\v4.0.30319 directory). See the example below:
- Include this new proxy class (containing the context object and the data classes) in your WP7 application.
- Use the class to call out to the service as necessary:
NetflixCatalog ctx =
new NetflixCatalog(new Uri("http://odata.netflix.com/Catalog/"));
var qry = from p in ctx.People
where p.Name == "Stanley Kubrick"
// Create DataService query since we're not
// using a DataServiceCollection
var dsQry = (DataServiceQuery<Person>)qry;
var result = dsQry.EndExecute(r).FirstOrDefault();
if (result != null)
Titles = result.TitlesDirected;
catch (Exception ex)
Note that you need to use a Dispatcher as this call is *not* guaranteed to be called on the UI thread. This was the one piece that was unexpected. Once I marshaled the update to the UI thread, all worked perfectly.
Here's the example: download
When you say
"Download the Windows Phone 7 OData Library here" the "here" part seems to be missing.
Already fixed it Joe...but thanks!
Shawn, do you have any insight into the relative performance for the various ways one could consume data from the web in a Phone application? I've heard that OData is kind of expensive in terms of serialization/deserialization. Certainly if one is consuming a data source where that's the only option, it makes sense to use it, but if one is in control of both the client and server, there are better choices. Any thoughts?
As far as cost of serialization, the cost is about the same for WCF or RIA Services. They were all within 1% of each other in perf tests on the desktop. Hard to tell if on the phone it would be much different.
Looks like the zip available via the download links is empty. Or is it just me? Either way, thanks for the info.
Should be fixed now...but you may need to clear your cache or use a different browser so it actually downloads the new file.
i have a problem with adding new entity using OData
private void SaveNewProduct()
MyEntities context = new MyEntities(new Uri("http://127.0.0.1:85/MyDataService.svc/"));
catch (DataServiceRequestException ex)
throw new Exception("An error occurred when saving changes.", ex);
private void SaveNewProduct_Completed(IAsyncResult result)
MyEntities context = result.AsyncState as MyEntities;
DataServiceResponse response = context.EndSaveChanges(result);
EndSaveChanges throws the NotSupportedException http://www.screencast.com/users/Shevch_Den/folders/Jing/media/19ad507c-0c86-4c56-8572-84e2e895b1d5.
Do you have any idea how to fix it?
Most likely your server-side configuration isn't set up to allow writing to the database.
What would be the main advantages to consuming an OData endpoint instead of a SOAP endpoint (exposed from RIA services)
You mentioned the tooling wasn't there (Add Service Reference) yet. Do you know if it will be in RTW bits?
Any idea why the query fails when I replace the constants with variables? I get a MethodAccessException. Works fine on full Silverlight client.
var qry = from p in ctx.People .Expand("TitlesDirected/Genres")
where p.Name == director // director is variable instead of const string
Any idea how this can be done?
I assume its a bug. I am hoping there is a fix when they rev the library.
I was able to work around it using CreateQuery and AddQueryOption:
var qry = ctx.CreateQuery<People>("People").Expand("TitlesDirected/Genres").Expand("TitlesDirected/Languages").AddQueryOption("Name", director);
Not as pretty, but with some extension methods it can be made strongly typed as well.
Still expect them to fix it though.
I've reported it to the OData guys for you. Hopefully it will get fixed sooner rather than later. You could make it simpler though and just take your original query and add the query option.
Ok this is too funny and I had to share it with you.
I am working on a LightSwitch article and trying to get it to Print. you can use a button but if you try to do say a "MessageBox.Show("Hello World!")" you get the obvious thread execution error.
LightSwitch does provide a method to show a MessageBox but of course I'm really trying to show a Print Dialog.
Anyway, I decided to just look at the articles on SilverlightCream and I clicked on yours. then staring me right in the face was "Deployment.Current.Dispatcher.BeginInvoke"...
I am working through this example but using an Azure oData enabled database. The proxy class created fine, but I am getting two errors in the code below. First, on the Begin Invoke ("cannot convert lambda expression to system.delegate") and second on the result.name ("Cannot implicitly convert type 'string' to 'System.Collections.ObjectModel.ObservableCollection<TechBioModel.User>").
Users = result.Name;
I was able to bring in the NetflixModel.cs and get that to work so I'm not sure where mine is going wrong. Everything else looks the same. Thanks.
Its a little confusing as you're treating the result as an object where as Users is a collection.
Just letting people know that the latest SDK for RIA Services exposes ODATA as
The "odata" at the end is important if you want datasvcutil to pick it up otherwise you get the dreaded "404" error page not found!
Why that is technically true, they don't expose much of the spec except read-only entities; no relationships or full, rich queries. As they've said, the OData support is a "down-payment on OData integration".
Hi Shawn, per your comment above I realized my mistake and fixed that, but I am getting the error: An Error Occurred while processing this request on the line:
result = dsQry.EndExecute(r).FirstOrDefault();
What is interesting is that as I step through your code, the Expression property of qry also states "Could not evaluate expression" but nothing is thrown when it executes on the line above. However, in my code, an error is thrown. I have looked at this all evening and can't find where the difference is. My query is a standard LINQ query as well:
var qry = from u in context.Users.Expand("Docs")
where u.ID == 113
I can't imagine this is an oData or LINQ error since both sets of code see the same Expression error, but I'm not sure why mine would catch it and yours not. What magic did you work on yours? :-)
I don't know why its happening exactly. Have you looked at the conversion to URI syntax and see if that works natively?
Shawn, thanks for this. I just confirmed that this info continues to work fine for the release build of WP7.
With today's new updates to the OData WP7 client library your code is no longer valid. Just a heads up that people may start asking why it does not work.