Creating an OData Publisher
I did a simple overview of OData in a previous post and on our recent Developer Smackdown Podcast (Episode 23) Clark and I talked about the capabilities and how you can use the OData standard to publish all kinds of data without knowing exactly how your consumers will use it. In this post I will show how you can utilize Entity Frameworks and create an OData service VERY easily. I will do this in Visual Studio ‘08 as well as 2010 since Microsoft loves to add a little confusion to the mix and changed the names of WCF/ADO.NET Data Services and how you initially get at them as VS projects.
First of all, “ADO.NET Data Services” in .NET 3.5 SP1/VS 2008 is now “WCF Data Services” in .NET 4/VS 2010. The original name was “Project Astoria”. Depending on the timing, blogs and articles on the net may be using any of those names.
VS 2008/.NET 3.5 SP1 (with Data Services Update – link below):
For these service applications I installed the AdventureWorks demo database that you can get on CodePlex which can be installed in a SQL Server database. I installed locally in SQL Express.
1. Start Visual Studio and create a WCF Service Application. OK, so there’s more confusion. Why isn’t there an ADO.NET Service Application. Dunno. But this is an easy way at getting the initial project in place. We will actually delete the service that this template creates and use an ADO.NET Data Service.
If you look at your solution, you will see something like this:
2. Delete the service class and interface. They will just get in the way otherwise.
3. Add a new item to the project. Select Web and an “ADO.NET Data Service”. In a moment of pure inspiration I named mine “ODataService.svc”.
If you look at your references, you will see that several new assemblies were added. System.Data.Entity, System.Data.Services, System.Data.Services.Client and System.ServiceModel.Web are all added.
4. The next thing is to add the database. I did this through Entity Frameworks. Some people like EF, some don’t. Thing is, EF makes this exercise stupid easy so I added a new item “ADO.NET Entity Data Model”.
5. This will start the wizard and the next step is to “Generate from database” and click Next.
6. Choose your connection and create the connection string.
7. Pick the tables that you want to publish and Finish.
System.Security gets added to the references and the EF data model also gets added.
8. So you have all the parts but there is code missing. In the data service code file “YourServiceName.svc.cs” or whatever your file name is, there are some changes. First, for OData to work the service inherits from the “DataService” class and you have to pass in your data type. In my example, the type generated from the EF wizard is “AdventureWorksLT2008Entities”. As a result my class definition for the service is:
public class ODataService : DataService<DataEntities.AdventureWorksLT2008Entities>
9. Inside the “InitializeService” method of your new service you will need a few lines of code as well. Especially since out of the box that method contains nothing but comments. Unfortunately, for those of us who preach dependency injection and the use of interfaces, you have to change the method parameter from an IDataServiceConfiguration interface type into a DataServiceConfiguration class type. It appears that the config type contains a required “DataServiceBehavior” property that the interface doesn’t know about.
10. Within the InitializeService method you add a few lines of code. Here’s the whole thing:
using System.Data.Services; using System.Data.Services.Common; namespace OdataWcfServiceApplication { public class ODataService : DataService<DataEntities.AdventureWorksLT2008Entities> { // This method is called only once to initialize service-wide policies. // DataServiceBehavior is part of the DataServiceConfiguration type - not IDataServiceConfiguration public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); // Use this especially for debugging. This line will respond with additional // info if an error is encountered config.UseVerboseErrors = true; // This line tells your service to use version 2 of the OData services. // Version 2 allows you to do more such as control paging of output config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } } }
OK, that’s it. You can now run the application, the service will be hosted locally and the browser will pop up. The result you get depends on the database that you use and the tables selected but it will appear something like this:
To test out the OData query capabilities just add your query to the end of the URL. For example, in my case I have a list of products that I can request. At the end of the URL I add “Product?top=10”. This says I want the listing of products but to limit it to the first 10. There are a lot of products in the database and if I didn’t filter then I would be waiting a while till all of the products were put in a list. Nice that I can do that.
Here is the output of that query:
If this is what you see…
and you want to see the raw data being sent back by the query (and why wouldn’t you?) you need to go into IE/Tools/Internet Options/Content tab/Feeds and Web Slices/Settings button and uncheck “Turn on feed reading view”. You may need to restart IE for that to take effect but after that you will see the raw data feed.
.NET 4/VS 2010
I’m just going to go over the differences here because for the most part, it is all pretty much the same.
- The first difference is with step 3. Because of the new names for the services, instead of creating an “ADO.NET Data Service”, create a “WCF Data Service”.
- In step 7, there is another option in the EF Wizard. “Pluralize or singularize generated object names” is a checkbox that is defaulted on. This is important because if I did everything else the same, the object that I exposed in the feed is not called “Product”, it’s now “Products” since the name was pluralized by EF. Obviously, queries must use the correct name or they don’t work.
I believe that’s it. Not much difference between the two. Just remember:
- To use OData in VS2008/.NET 3.5, you need to install the Data Services Update (link below) – It is now part of .NET 4
- As stated above, the object names may or may not be pluralized depending on the EF Wizard. “Product” != “Products”
- Queries are case sensitive. “Product” != “product”. If you are having trouble with a query take a look at the object names
- If you can’t see the raw data in IE, change the content setting in Internet Options (described above)
- If you publish OData, the query processing is done on your server so keep in mind how much it is accessed, how much data is being queried and the potential complexity of the queries as this relates specifically to sizing and bandwidth
Resources:
Data Services Update for .NET 3.5 SP1: update to .NET that installs the libraries that give you the OData capabilities.
Click here for Win7 and W2K8 R2.
Click here for all other OS versions.
