Tag Archives: OData

Add an OData Feed to Your App Using Web API

Adding a REST interface to your application using ASP.NET Web API is pretty well documented.  This post describes the creation of an OData feed through the same ASP.NET Web API techniques.  The example below uses an ASP.NET Web Forms application as the base since there are tons of these applications out there.  You can use this same technique in MVC apps as well.  Since everything in this environment is ASP.NET at the core, Web Forms, MVC and Web API can all exist side-by-side.  The only assumption for this post is that the applications utilize .NET 4.5.

One other note, it is relatively easy to combine Entity Frameworks with OData output.  This example describes the use of non-EF datasets.  Why? you ask.  Well, there may be many cases where the data is not coming from an EF source or maybe your data is stored or cached locally.  There are any number of reasons.  Ultimately, this example shows how to output your data in a standardized OData fashion including any part or all of the OData querying capabilities provided to the consumer of the service.

So, we start off with a standard Web Forms application.  Steps 1 and 2 listed here are not absolutely necessary, they are meant to structure the application in a similar form to that of an ASP.NET MVC application.  Doing this will make things it easier to manage.  If you start off with an MVC application, the folders will already exist.

1. Create a sub folder right off the main project and call it “Controllers”

2. Create a second sub folder right off the main project and call it “Models”

The Models folder should contain classes created to shuffle data around the application.  In an MVC application, view models can be held here to support and pass data to the views.  In this example, we will be creating a model that will describe the data provided in the OData interface.  The data here will be a simple list of meetings.  Obviously, it could be any data you want but since we are using OData, it should start with a larger grouping (or groupings) of data.  If your interface will always return a single a single record or object, then the non-OData Web API interfaces are better.  But, if you are starting with a relatively large set of data and then (through queries) trim down the output to a smaller subset or even a single record, OData will work very well.

You should now have something that looks like this:

image

3. Add a class that will manage the meeting data:

SNAGHTML12f21b9e

using System;

namespace FormsWithWebApiAndOData.Models
{
    public class Meeting
    {
        public string Id { get; set; }
        public DateTime MeetingDate { get; set; }
        public string Title { get; set; }
        public string Leader { get; set; }
    }
}

4.  Add the controller that will provide all of the REST access.  Right-click “Models” and add a “Web API Controller”.  You can add this through the normal “Add Item” approach.  You may also have a menu option to add the controller directly. Name the controller “MeetingsController.cs”.  It is important that the name of the controller class ends in “Controller.cs” since ASP.NET MVC and Web API use “Convention over Configuration”.  Naming convention is the way many components are found as the application executes.

image

SNAGHTML130094f2

You will now have a project structure that looks something like this:

image

The application must understand how to process requests that are destined for the OData REST service that we are creating.  To do this, the application must contain the ASP.NET Web API and Odata components (assemblies).  This is easy to do through NuGet.

 

5. Right-click on the project and select “Manage NuGet Packages…”.  When the NuGet dialog appears, enter the following search to make things easier: “ASP.NET Web API OData”.  When the package appears, click “Install”.

SNAGHTML1311ac97

We can now add the OData functionality.  The controller must be modified to provide the OData REST access point to the Meeting data.  We need to add some code to create the data that is used in the example.

 

6. Open MeetingsController.cs and add the following code at the top of the class.  It will then be the source of the OData feed.

image

    private readonly IList<Meeting> _scheduledMeetings;

    public MeetingsController()
    {
        _scheduledMeetings = new List<Meeting>
        {
            new Meeting { Id = "1", Leader = "Mark Nichols", MeetingDate = new DateTime(2013, 1, 17), Title = "Project X Planning" },
            new Meeting { Id = "3", Leader = "Jim Phelps", MeetingDate = new DateTime(2013, 2, 8), Title = "Mission Discussion" },
            new Meeting { Id = "6", Leader = "Barney Collier", MeetingDate = new DateTime(2013, 3, 12), Title = "Advanced Device Technology" },
            new Meeting { Id = "7", Leader = "Willie Armitage", MeetingDate = new DateTime(2013, 5, 28), Title = "Maintaining a Strong Presence" },
            new Meeting { Id = "9", Leader = "Cinnamon Carter", MeetingDate = new DateTime(2013, 2, 15), Title = "Company Fashion" },
            new Meeting { Id = "10", Leader = "Rollin Hand", MeetingDate = new DateTime(2013, 1, 21), Title = "Magic Selling" }
        };
    }

Web API injects a standard set of methods for HTTP GET, POST, DELETE, and PUT to get you started.  In this example are really only interested in a GET that will allow all necessary OData queries so you can actually delete all of the provided methods.  We’ll add our own GET in the next step.

 

7. Add the following method to the controller right below the constructor code you added in the last step.

    // GET api/Meeting
    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    public IQueryable<Meeting> Get()
    {
        return _scheduledMeetings.AsQueryable();
    }

You will need to add these “using” statements:

using System.Web.Http.OData.Query;
using FormsWithWebApiAndOData.Models;

Notes on the HTTP GET method that we just added:

  • “IQueryable” (part of Linq) is the interface that you must return so that OData can provide the appropriate query and output capabilities.
  • The List that contains all of the meeting data can be made to output its data through the IQueryable interface by using the “AsQueryable()” extension method (also provided by Linq).
  • The attribute “QueryableAttribute” enables querying using the OData syntax.
  • AllowedQueryOptions provides an easy mechanism for limiting the types of queries that are allowed to be processed.  This is especially important when dealing with significant amounts of data.  You can stop queries that would normally spend tons of time processing on your server.  In this example, I’ve opened up all queries so you can try all of the OData options.

 

We’re almost done. Lastly, we need to create a URL path that will send OData requests to the method that we just created.

8. Open Global.asax and in Application_Start add the routing information that will transfer control to the newly created method.

    GlobalConfiguration.Configuration.Routes.MapHttpRoute(
        name: "ODataRestApi",
        routeTemplate: "api/v1/{controller}"
    );

“MapHttpRoute” sets up the URL routing information so that everything can flow through the controller we just created and then into the method.  “name” is arbitrary and has no effect on the routing – it is just for organizational purposes.  “routeTemplate” indicates what URL pattern will be captured.  In this case the URL must start with “api” and then, it must contain “v1”.  The “v1” is an indicator of the version of the API.  Version your API’s and you will always be better off.  “{controller}” acts as a variable and captures the name of the controller that contains the functionality that you want to call.  In our case, the name of the controller is “MeetingsController” but because of convention, only the “Meetings” part must be used, the ASP.NET frameworks take care of the rest of the mapping.

The only thing left to do is run it.  Execute the application and try some of the following queries (port number will vary of course):

http://localhost:14129/api/v1/meetings

http://localhost:14129/api/v1/meetings?$filter=(Leader eq ‘Mark Nichols’)

http://localhost:14129/api/v1/meetings?$top=2

http://localhost:14129/api/v1/meetings?$filter=MeetingDate eq datetime’2013-01-17′

You now have OData query control over pretty much any kind of data you want to pump through your API.  You can use these queries in AJAX calls or even right from your browser.

 

Formatting the Output

This part is not necessary for the operation of the queries BUT you may want to control the data format coming back through the optional OData “format’=” query parameter.  This capability is always there through setting the content headers in the HTTP request but OData gives you another option in the query.  You just have to turn it on:

In my tests, if I used Internet Explorer (I was using V10), all my requests would return JSON data.  If I used Chrome, XML would always come back.  So, I added the some code to give me the option of XML or JSON in the query.

Add the following code in Global.asax right before the call to MapHttpRoute :

    // XML or JSON output selection
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");

You will need to add this using statement:

using System.Net.Http.Formatting;  // "AddQueryStringMapping"

Now you should be able to do things like this:

http://localhost:14129/api/v1/meetings?$filter=(Leader eq ‘Mark Nichols’)&$format=xml

image

http://localhost:14129/api/v1/meetings?$top=2&$format=json

image

image

 

References:

OData Developers Reference: http://www.odata.org/developers/

OData in ASP.NET: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api

Limiting OData Query Options: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options

OData Security: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-security-guidance

OData is Case Sensitive!

One last thing, the OData query syntax is case sensitive.  So, if you don’t get back what you think you should have with a particular query, check the case of the query commands (usually lower case), filter fields (depends on your data classes), etc.

Create an OData Feed with VS 2008 and 2010

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.

image

If you look at your solution, you will see something like this:

image

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”.

image

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”.

image

5. This will start the wizard and the next step is to “Generate from database” and click Next.

image

6. Choose your connection and create the connection string.

 image

7. Pick the tables that you want to publish and Finish.

image

System.Security gets added to the references and the EF data model also gets added.

image

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:

image

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:

image

If this is what you see…

image

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:

OData.Org

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.

Technorati Tags: ,,

OData – Getting Started

Just got back from the MIX10 conference. Hanging out with by buddy Clark Sell and doin podcasts, we took in and tried to absorb as much as we could.  Of course the big news was around Windows Phone 7 Series and Silverlight 4 but there was also quite a buzz about OData.  Personally, the moniker is a little boring but who am I to judge – the capability is the big thing.  If you haven’t heard about it, it is an open protocol for working with ATOM and JSON data feeds.  Just from that description, you might be thinking “so what” – well, keep reading. This protocol isn’t just so you can publish or consume feed data, you know you can do that.  But, now you can output a customizable data feed without knowing the full intention of the consumer ahead of time.  In other words, you can provide a data feed service that can directly respond to the consumer’s requests/queries and output the feed with only the data requested in the way best suited for them to consume and you don’t need a custom set of API endpoints to do it.

OData-logo

Some OData Facts:

  • The OData spec is around the protocol, not the implementation. (BTW, already, there are libraries available for JavaScript, PHP, Java, Objective-C and .NET)
  • It is based on REST calls through HTTP so (GET, PUT, DELETE, POST, etc.) so strictly speaking, you don’t even need a client api to access OData feeds – you could do it from a browser URL/Address line.
  • Feeds can be output in ATOM as well as JSON again, from the same endpoint.
  • The protocol is for reading from AND writing data back to a data source
  • Security around the data can be enforced

Try it:

Go to http://services.odata.org/Northwind/Northwind.svc/

The OData site has provided access to the sample Northwind database. When you get there you will see all of the data that you can access and query against. 

Notice from the result set that there is a list of all the different collections of data that you can access from this single service.  You have Customers, Shippers, Products, Suppliers, Regions, Orders, etc.  All you need to do to access any one of the collections is to type the collection name in the URL.  This example will return a list of all products:

http://services.odata.org/Northwind/Northwind.svc/Products 

Note: at this point things are case-sensitive so “Products” works but “products” won’t.  

image

If you are in Internet Explorer, and don’t see the detailed data stream, you might want to go to “Tools \ Internet Options

\ Content \ Feeds and Web Slices \ Settings”.  Then, uncheck “Turn on feed reading view”.  After that, you will see the actual feed data in the browser.

Cool. But, what if I only want products with a unit price over 50.00?  Add a filter:

http://services.odata.org/Northwind/northwind.svc/Products?$filter=UnitPrice gt 50

Notice that the UnitPrice is typed and is a Decimal.  Others are 16bit integers, 32bit integers, booleans, etc.

Now, sort:

http://services.odata.org/Northwind/northwind.svc/Products?$filter=UnitPrice gt 50&$orderby=UnitPrice

Would you rather the data being sent back be in JSON format?

http://services.odata.org/Northwind/northwind.svc/Products?$filter=UnitPrice gt 50&$orderby=UnitPrice&$format=JSON

All of this is being done through a single endpoint.  Even more important, it is being done with a standard set of query parameters which means that you will know how to publish and consume (i.e., select, extract, filter, sort and format) data coming from any feed that uses the OData Protocol.  Schweeet!

Next up…Create your own publisher with WCF Data Services.

Resources and Info:

Technorati Tags: ,,,