WCF Data Services OData consumption

download code

Introduction

This tutorial is part 2 of the introduction to OData and WCF Data Services. To get the background skinny on WCF Data Services, visit this blog. Now on to your First Data Service application.

First open Visual Studio and Create a New Project using the WCF Service Application template. Let name it MyFirstDataServices. As discussed in the last article, Data Services does NOT self host. It needs another application that already knows how to self host. This is why when you are creating a project, there is no WCF Data Services option. You can use either anything that self hosts, ASP.NET (MVC or WebForms), Console Application, WCF Service application etc… In this tutorial we are using the WCF Service application, but you can use any of the above mentioned and still follow the proceeding tutorial without much deviation if any at all from the following steps.

 

image

 

After the project is created, you can now right click the application and select add new item. On the menu on the left, select Web and choose to add a WCF Data Service. Lets leave the default name of WcfDataService1.svc. Click Add.

image

 

Now you are about to see some daunting stuff if you haven’t read up much on the Data Service terminology. First thing we want to do is have some data that we want to expose right? Well, in this demo, we are not going to use Entity Framework and instead use the Reflection technique. If anyone wants an Entity Framework example, let me know and I’ll add one. Reflection is just the simplest to demo without much configuration.

So lets add the famous Person.cs class and add public properties ID, Name, Age and Title.

** Note ** ID is required and must be unique otherwise, OData will not know how to expose it as a list because it does not do its own indexing! ID must be shown exactly as it is below. If you want it to have a different name when being exposed (almost like a DTO), you may use the data annotation [DataServiceKey(“someNewName”)]. This will allow Data Services to still have it’s cake and you can eat it too :).

Upon completion, your class should look like this.

[DataServiceKey("Id")]
public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Title { get; set; }

}

Ok, so far so good, lets make a context class. What’s a context you say? Basically it is the same as what many call a Repository class. it hides all the calls to do CRUD calls to an access layer of some kind. Lets call this class PersonContext.cs.

So, now we have this class right. Ok there are a few things we need to understand about OData and Data Services. Data Services require that the Context being used has an IQueryable property exposed. This allows the Data Services to serve up the data in it’s own way using OData syntax. (explained later). In order to do this, we will first create a private field that is of type List<Person>. This allows us to easily use features like the Add() method. Then we will populate this private field using a GetPersonsData method that takes no parameters and just fills a new List of Person and returns it to the private field with Person objects in the constructor.

The final piece will be to add a public IQueryable property that is exposed for the Data Service. This will in effect be an Entity as far as Data Service is concerned. It is pretty much how Entity Framework exposes its context as well. Its get property will return the private List that was filled during instantiation via the constructor. It is converted to a queryable object using the AsQueryable method on teh fly. Upon completion, your PersonContext class should like this:

public class PersonContext
{
    private static List<Person> _personList;

    public IQueryable<Person> Persons { get { return _personList.AsQueryable(); } }


    public PersonContext()
    {
        _personList = GetPersonsData();
    }

    public List<Person> GetPersonsData()
    {

        List<Person> persons = new List<Person>();
        persons.Add(new Person()
        {
            ID = 1,
            Name = "Gregg",
            Age = 31,
            Title = "Software Engineer"

        });

        persons.Add(new Person()
        {
            ID = 2,
            Name = "George",
            Age = 38,
            Title = "Software Engineer"

        });

        persons.Add(new Person()
        {
            ID = 3,
            Name = "Rachel",
            Age = 21,
            Title = "Waitress"

        });

        return persons;

    }

}

Now the last step for our simple example is to add the proper pieces that are still throwing compile errors in the WcfData Service1.svc file. To fix this, start by going to line 16, where the DataService is expecting a data source, it actually has a TODO comment that states “/* TODO: put your data source class name here */”. This is where the PersonContext goes.

Now to set the configuration of the Data Service. Although there are many configurations, for now, only one that is commented out is required. This is line 23:

// config.SetEntitySetAccessRule(“MyEntityset”, EntitySetRights.AllRead);

Uncomment this out and inside the double quotes that says MyEntityset, replace that with Persons. This is telling the Data Service that it will find the IQueryable object inside PersonContext named Persons. This is because that is the public property we exposed in the above code. We can also use * here to denote exposure of all public queryable objects in PersonContext.

If you do by mistake type in the wrong value, like using Person ( the actual object name, not the queryable type), you will receive an error similar to this one:

image

Basically it is telling you it knows nothing about the Entity set Person, which is correct.

Ok, so now lets test this bad boy. Click on the WcfDataService1.svc and Run the debugger. This should open a web page to the local host in your favorite browser.

If you get a directory listing like the image below, again select the link that says WcfData Service1.svc. NOT the one with svc.cs!

image

Now you should be presented with an atom XML page that tells you the encoding and collection type, in this case Persons.

image

If you would just like to display all the Person objects, you may by adding Persons in front of the current Uri like so: http://localhost:[port]/WcfDataService1.svc/Persons. Obviously, you need to replace the port with whatever you are using.

Now, lets say that you want to see what Person has an ID of 1, lets use our special OData syntax to get it.

at the end of your url in the address bar, append Persons(1). This will return you the object thats ID is 1. See below for what you should see. It will give you the Name, Age and Title of this Person as well as the last date it was updated.

image

Update will have to be another tutorial extended to this one, but you can also see the link to update the Person as well in the following line.

<link rel=”edit” title=”Person” href=”Persons(1)” />

 

Now obviously, this would be an in memory edit, but still, it proves it’s point.

 

Lets do one other OData syntax that is of interest called filter. The filter keyword with a ‘$’ in back of it signals OData that we want to do some special filtering on our query and not just the basic calls. To get a Person by a particular name, you can use something like:

http://localhost:[port]/WcfDataService1.svc/Persons?$filter=Name eq ‘Gregg’

 

Now, if you are familiar with GET in HTTP, the ? at the end of an address denotes a GET is about to happen over HTTP to get ‘some data’. Now, the $filter= says to OData “Hey I’m not interested in basic queries, I want to filter on that stuff. The after the =  is the actual filter, in this case, we are looking for any objects of type Person who’s name is equal ( that’s what eq stands for) to ‘Gregg’. The syntax can be a little weird at first, but if you are used to Lamda and LINQ, you will pick this up in no time. There are skip, top, orderBy etc… all of which are triggered by the filter command.

That’s it for now, hope you enjoyed!!

 

Happy Coding :)!!

Advertisements

About Gregg Coleman

I am Senior-level Software Engineer working primarily these days with .NET. I have a good working knowledge of ASP.NET MVC, Web Forms, WCF web services and Windows Services. I spend much of my time in the Web Services (SOAP and REST) world in my current job designing and implementing various SOA architectures. I have been in the software engineering industry for about 6 years now and will not now nor ever consider myself an "expert" in programming because there is always so much to learn. My favorite thing about designing software is there are always new emerging technologies and something to learn every day! My current job has me spending much of my job on the bleeding edge of technologies and changing gears all the time, so I'm never bored and always challenged. On my spare time I enjoy weight training, reading and venturing to new places near by. Of course programing and learning new technologies are another hobby of mine.
This entry was posted in Uncategorized. Bookmark the permalink.

1 Response to WCF Data Services OData consumption

  1. Pingback: REST, OData and Atom | Object Reference Hell

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s