OData
(Open Data Protocol) lets you expose your resources and let the clients
directly do the queries over it. Earlier when we used to use SOAP, you expose
some methods, which performs some operations over the data returns back you the
results, and if any client needs some specific data, then we used to changes
our services by exposing down a new method which returns the needed output. But
with OData also known as Resource Oriented architecture, we can just expose the
resources or the data and let the client make the queries according to the
requirement.
Here
in this article of mine I will show you how to create a simple OData Service
and let the client make queries just like SQL queries over it to retrieve the
required data. Queries can be made by just specifying the filter expressions in
the URL only.
So to
start with I have created a WCF Service Application.
After creating we need to create a Data Service, which is
done by just the following, some simple steps: Right click on the WCF
application, and Add WCF Data Service as shown in the screenshot below.
As soon as it is done, you will see the generated service
file:
public class SampleWCFDataService : DataService< /* TODO: put your data source class name here */ >
{
// This
method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO:
set rules to indicate which entity sets and service operations are visible,
updatable, etc.
//
Examples:
//
config.SetEntitySetAccessRule("MyEntityset",
EntitySetRights.AllRead);
//
config.SetServiceOperationAccessRule("MyServiceOperation",
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
}
I have highlighted in yellow, to get the service ready to be
used we need to specify the Data Source Class, this can be achieved by simply
providing Entity Framework Model for a particular database. So what this Data Source
class should support is IQueryable properties over the exposed entities. Entity
Framework model exposes all your entities as IQueryable properties. It allows directly
exposing your tables and letting the client make queries over it by using
Filter Expressions.
But for the sake of keeping it simple I am not creating
Entity Framework model and will be creating a Data context class which have
IQueryable properties.
So let’s look into how to create DataContext Class, before
that we need to create some entities (Data Service Entities) which will be
exposed as IQueryable entities via this DataContext class, here I will be
creating a single entity User:
[DataServiceKey("Id")]
[DataServiceEntity]
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Attribute has been added specifying the User class as Data
Service Entity. Now we will create a context class:
public class SampleContext
{
#region
Static Constructor
/// <summary>
/// In this static constructor i am creating some data which
will be filled into users list, the purpose of creating static constructor is
that it will be executed once
/// on the creating of very first object and fills in some
data into the users list which we can use to run through the demo.
/// </summary>
static SampleContext()
{
users = new List<User>();
User user1 = new User();
user1.Id = 1;
user1.Name = "Abhishek1";
user1.Age = 20;
User user2 = new User();
user2.Id = 2;
user2.Name = "Abhishek2";
user2.Age = 30;
User user3 = new User();
user3.Id = 3;
user3.Name = "Abhishek3";
user3.Age = 40;
users.Add(user1);
users.Add(user2);
users.Add(user3);
}
#endregion
#region
Private Members
static IList<User> users;
#endregion
#region
Public Methods
public IQueryable<User> Users
{
get
{
return users.AsQueryable();
}
}
#endregion
}
Now you can see that I have provided the Data Source for the
Data Service we created earlier to this context class:
With this we are ready to use this service:
So above you can see that the Data Service is working, and
the format in which it is displayed above is the Atom pub format. By default it
doesn’t exposes the Data Context we created and set in the Data source in the
service. For achieving so what we have to do is in the service code just
uncomment the code highlighted in yellow, what this code do is, it defines the
Entity access rule for the entities (Which all entities are needed to be
exposed) so what we doing is we are exposing the entity Users below and are
setting the Access level to Read, so we are only allowing Read operations.
public class SampleWCFDataService : DataService<SampleContext>
{
// This
method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO:
set rules to indicate which entity sets and service operations are visible,
updatable, etc.
//
Examples:
config.SetEntitySetAccessRule("Users", EntitySetRights.AllRead);
//
config.SetServiceOperationAccessRule("MyServiceOperation",
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
Now if you will access the Service again you will see
something like below:
So here we get a new collection users, which we can use in
the URL (Same as REST format) to get the users collection.
So here we are getting the Users Collection in the Atom PUB
format shown above. So what’s the use of this is we can make a request to this URL
(http://localhost/SampleWCFDataService.svc/Users)
from a Web Page or a JavaScript file (Data can be returned in JSON format) can
use the output i.e. Users list in the Web Page.
If we understand the format above we can see that it already
provides the things to determine how we can query down the Data Source or can
user filter expressions in it. Just for the sake of understanding I am
formatting the output above in XML Format.
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="http://localhost:51937/SampleWCFDataService.svc/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>http://localhost:51937/SampleWCFDataService.svc/Users</id>
<title type="text">Users</title>
<updated>2013-10-08T14:44:06Z</updated>
<link rel="self" title="Users" href="Users" />
<entry>
<id>http://localhost:51937/SampleWCFDataService.svc/Users(1)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(1)" />
<title />
<updated>2013-10-08T14:44:06Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">1</d:Id>
<d:Name>Abhishek1</d:Name>
<d:Age m:type="Edm.Int32">20</d:Age>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:51937/SampleWCFDataService.svc/Users(2)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(2)" />
<title />
<updated>2013-10-08T14:44:06Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">2</d:Id>
<d:Name>Abhishek2</d:Name>
<d:Age m:type="Edm.Int32">30</d:Age>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:51937/SampleWCFDataService.svc/Users(3)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(3)" />
<title />
<updated>2013-10-08T14:44:06Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">3</d:Id>
<d:Name>Abhishek3</d:Name>
<d:Age m:type="Edm.Int32">40</d:Age>
</m:properties>
</content>
</entry>
</feed>
So if we type in the above highlighted command directly into
the Address bar we will get something like below which is the very first user
in the list:
<?xml version="1.0" encoding="utf-8"?>
<entry xml:base="http://localhost:51937/SampleWCFDataService.svc/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>http://localhost:51937/SampleWCFDataService.svc/Users(1)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(1)" />
<title />
<updated>2013-10-08T14:53:39Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">1</d:Id>
<d:Name>Abhishek1</d:Name>
<d:Age m:type="Edm.Int32">20</d:Age>
</m:properties>
</content>
</entry>
This is how the service works and we can actually directly
consume the data into the Web Page where we need to. Now we will look into how
to use filter expression directly while accessing the Data Service and retrieve
the results. There are lot filter expressions available:
- And
- OR
- Less Than(equal to)
- Greater Than(equal to)
- Not Equal
- Ends with
- Starts With
- Length
- Index Of
- Replace
- And many more…
How to actually use them, so if I consider the above
scenario in which we are getting the Users collection, now if I want to get all
the users which are actually having age greater than 22, then we can simply
make a filter query(http://localhost/SampleWCFDataService.svc/Users?$filter=Age
gt 22) and get the results.
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="http://localhost:51937/SampleWCFDataService.svc/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<id>http://localhost:51937/SampleWCFDataService.svc/Users</id>
<title type="text">Users</title>
<updated>2013-10-08T15:13:42Z</updated>
<link rel="self" title="Users" href="Users" />
<entry>
<id>http://localhost:51937/SampleWCFDataService.svc/Users(2)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(2)" />
<title />
<updated>2013-10-08T15:13:42Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">2</d:Id>
<d:Name>Abhishek2</d:Name>
<d:Age m:type="Edm.Int32">30</d:Age>
</m:properties>
</content>
</entry>
<entry>
<id>http://localhost:51937/SampleWCFDataService.svc/Users(3)</id>
<category term="SampleService.User" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="User" href="Users(3)" />
<title />
<updated>2013-10-08T15:13:42Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">3</d:Id>
<d:Name>Abhishek3</d:Name>
<d:Age m:type="Edm.Int32">40</d:Age>
</m:properties>
</content>
</entry>
</feed>
So as it should be it is returning only two users, now let’s
make it something like greater than 22 and less than 35(http://localhost/SampleWCFDataService.svc/Users?$filter=Age
gt 22 and Age lt 35) which should return only one result. Now here we have
seen the use of both Greater than, less than and the “and” expressions.
Similarly you can use the other available filter
expressions. You can also download the sample application(From Here: Download) to see the working.
No comments:
Post a Comment