WCF Data Services Providers

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

Open Data Protocal (OData) seems to be showing up everywhere in the Microsoft stack. SharePoint surfaces OData, Excel consumes OData, SQL Azure is built on OData, and SQL Reporting Services now renders OData. Any developer needing to share data from .NET with the OData ecosystem should first look at Windows Communication Foundation (WCF) Data Services. Using a set of standard Providers; WCF Data Services can turn .NET code into an OData Web Service. This article introduces the WCF Data Services Reflection Provider.

WCF Data Services Introduction

WCF Data Services is built on WCF. WCF is the.NET choice for consuming and implementing Endpoints. WCF provides a framework for implementing Web Services and other distributed process communication. The canonical WCF architectural figure from the MSDN documentation follows.

WCF Canonical Architecture
Figure 1: WCF Canonical Architecture, source: http://msdn.microsoft.com/en-us/library/ms733128.aspx

Any solution built on WCF must define three components address (A), binding(B), and a contract (C) (ABC).

Address is the Endpoint URI. A sample WCF Data Service address follows:

http://localhost:8000/Data

Often included in the address are items like protocol, port number, and a path into the Endpoint.

Binding determines how data is encoded and transmitted over the wire. Bindings handle encryption, transport, handshaking, and packaging.

Contract defines the shape of the data. For example: Contract determines how WCF should map a .NET class into a format that can be packaged and then transmitted to a client on the other side of an Endpoint. In WCF parlance this is call Serialization.

There is some overlap between these components. So, for example, a Contract can influence a Binding's behavior. Many developers find WCF difficult. I believe that much of the difficulty arises because WCF is architected to support all distributed computing forms. WCF Data Services simplifies how a developer works with WCF and OData. WCF Data Services provides the Binding, Contract, and influences the Address' formatting. Data Service developers are left to implement more mainstream .NET classes.

WCF Data Services enforces and implements OData conventions.

OData Overview

http://www.odata.org provides a complete OData introduction so the following summarizes OData core ideas.

OData builds on some common Web standards. Data is transmitted over HTTP. Create, Read, Update, and Delete (CRUD) are implement with HTTP operations like POST and GET. OData message/data formatting leverages Atom Publishing Protocal (AtomPub) and the JavaScript Object Notation (JSON). AtomPub and JSON schemas and conventions are defined in the specification. The specification also defines Endpoint (URI) navigation conventions.

WCF Data Services affixes OData onto WCF. Like all WCF services; implementing a WCF Data Service starts with configuring a host.

Configuring a Host

WCF offer two hosting models: IIS and self-hosted. Self-hosted means the Service runs in whatever executable a developer chooses, for example, a Console Application or a WPF Application. The following code demonstrates configuring the host.

Type serviceType = typeof(TestItemsDataService);
Uri baseAddress = new Uri("http://localhost:8000");
Uri[] baseAddresses = new Uri[] { baseAddress };
 
DataServiceHost host = new DataServiceHost(
    serviceType,
    baseAddresses);
 
 
host.Open();
 

DataServiceHost layers on top of WebServiceHost. The ServiceType parameter must be of type DataService<T>. Following is the Sample code SeriviceType definition.

[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class TestItemsDataService : DataService<TestItems>
{
    public static void InitializeService(IDataServiceConfiguration
                                config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.UseVerboseErrors = true;
    }
 
}
 

There will be more ServiceType details later in the article. InitializeService is called once during Service startup. In a more sophisticated implementation; a developer would define multiple "Entity Sets". I like to think of Entity Sets as the collection Property that contains the data. The sample code implements one Entity Set called Data. Invoking SetEntitySetAccessRule defines how the Entity Set will be accessed and updated. For example: a developer can restrict some EntitySets to be read-only. An asterisk "*" is a wildcard meaning all EntitySets.

Normally a service does not define VerboseErrors or IncludeExceptionDetailsInFaults. Since Exception details are omitted by default; both options are helpful when debugging services. DataServiceHost covers the WCF portion of WCF Data Services. Reflection Provider works with the ServiceType to surface data.

ServiceType and the Reflection Provider

WCF Data Services include several Providers. The Entity Data Model provider works with an Entity Data Model. Custom Providers are dynamic and the Reflection Provider works with static .NET classes. The core portion of the Data Service is comprised of the type supplied in DataService<T>. In the example this is the TestItems class. The TestItems class definition follows:

public class TestItems : IUpdatable
{
    static Dictionary<string,TestItem> _data = null;
 
    static TestItems()
    {
        _data = new Dictionary<string,TestItem>();
 
        _data.Add("One",new TestItem() { Id = "One", Payload = "This is One" });
        _data.Add("Two",new TestItem() { Id = "Two", Payload = "This is Two" });
 
    }
 
    public IQueryable<TestItem> Data
    {
        get { return _data.Values.AsQueryable(); }
    }
 
}
 

Typically a Service exposes a collection of data. Data Collections must be properties on the class that return an IQueryable<T>; like the Data Property in the sample code. A Property returning an IQueryable<T> is called an EntitySet. As stated earlier developers can control how an EntitySet is consumed.

When the Service starts the Reflection Provider scours the class supplied in DataService<T> for IQueryable<T> properties and surfaces IQueryable<T> properties as a Web Service in WCF Data Services. As stated earlier IQueryable<T> can accept any .NET class. The only stipulation a class supplied in IQueryable<T> is that the class must include a DataServiceKeyAttribute like in the following example.

[DataServiceKey("Id")]
public class TestItem
{
    public TestItem()
    {
        Id = "defaultId";
        Payload = "defaultPayload";
    }
 
    public string Id { get; set; }
    public string Payload { get; set; }
}
 

The key attribute should define the class instance's uniqueness much like a Primary Key on a database Table defines uniqueness between records. In the example only one class in the underlying collection can have the "One" Id value assigned to it.

A more advanced example allowing Updates to the underlying Service is beyond the scope of this article, but will be covered in future articles.

Once the Self-hosted service is started navigation requires following the OData URI conventions.

Navigating the Service

The URL below navigates to all the data on the Data Property on the TestItems class.

http://localhost:8000/Data

As long as Atom feeds are set to render as XML a snippet of the OData like the output below will render in the browser.

<title type="text">Data</title> 
<id>http://localhost:8000/Data</id> 
<updated>2011-10-25T01:16:20Z</updated> 
<link rel="self" title="Data" href="Data" /> 
- <entry>
<id>http://localhost:8000/Data('One')</id> 
<title type="text" /> 
<updated>2011-10-25T01:16:20Z</updated> 
- <author>
<name /> 
</author>
<link rel="edit" title="TestItem" href="Data('One')" /> 
<category term="Test.OData.Server.TestItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
- <content type="application/xml">
- <m:properties>
<d:Id>One</d:Id> 
<d:Payload>This is One</d:Payload> 
</m:properties>
</content>
</entry>

Navigating to a specific class would be as follows.

http://localhost:8000/Data('One')

A more complete introduction to OData navigation is beyond the scope of this article, but will be covered in a future article. By default WCF Data Services renders data in AtomPub format.

Conclusion

OData's simplicity and common underlying Web standards have made it a popular Data protocol in the Microsoft stack. .NET Developers who want to build an OData Web Service should try WCF Data Services. WCF Data Services includes several Providers that surface data from .NET classes.

Resources

"Reflection Provider"



About the Author

Jeffrey Juday

Jeff is a software developer specializing in enterprise application integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server. Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security. Jeff is a Microsoft BizTalk MVP. Jeff spends his spare time with his wife Sherrill and daughter Alexandra.

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date