Creating a Data Service Provider – Part 4 – Minimal Running Service

This is Part 4 of my ongoing series of posts showing how to create an Custom Data Service Provider.

NOTE: I’ve done a little refactoring to the code in Part 3 to simplify the code in this post, so be sure to check that out if you’ve been following along.

In Parts 2 & 3  we hooked up our implementation of IServiceProvider and IDataServiceMetadataProvider.

Exposing IDataServiceQueryProvider

Now we need to implement IDataServiceQueryProvider, and refactor our IServiceProvider implementation to expose it:

public abstract class DSPDataService<T> :
DataService<T>, IServiceProvider
{
public IDataServiceMetadataProvider _metadata;
public IDataServiceQueryProvider _query;

    public DSPDataService()
{
_metadata = GetMetadataProvider(typeof(T));
_query = GetQueryProvider(_metadata);
}
public object GetService(Type serviceType)
{
if (serviceType == typeof(IDataServiceMetadataProvider))
return _metadata;
else if (serviceType == typeof(IDataServiceQueryProvider))
return _query;

else
return null;
}

    public abstract IDataServiceMetadataProvider
GetMetadataProvider(Type dataSourceType);

public abstract IDataServiceQueryProvider
GetQueryProvider(IDataServiceMetadataProvider metadata);

}

Notice there is a new GetQueryProvider(…) method that your DataService must override.

The IDataServiceMetadataProvider might be needed by the IDataServiceQueryProvider so it is passed as an argument.

public class Sample : DSPDataService<object>
{
… see part 3 for the rest of code …

public override IDataServiceQueryProvider
GetQueryProvider(IDataServiceMetadataProvider metadata)
{
return new DSPQueryProvider<object>();
}

}

Implementing IDataServiceQueryProvider

If you only want to be able to see the ServiceDoc and $metadata you only need to implement the CurrentDataSource property, the rest of the methods are only called when you actually query one of the ResourceSets:

public class DSPQueryProvider<T> : IDataServiceQueryProvider
{
T_currentDataSource;
public object CurrentDataSource
{
get {
return _currentDataSource;
}
set {
_currentDataSource= value as T;
}
}

public object GetOpenPropertyValue(
object target,
string propertyName)
{
throw new NotImplementedException();
}
public IEnumerable<KeyValuePair<string, object>>
GetOpenPropertyValues(object target)
{
throw new NotImplementedException();
}
public object GetPropertyValue(
object target,
ResourceProperty resourceProperty)
{
throw new NotImplementedException();
}
public IQueryable GetQueryRootForResourceSet(
ResourceSet resourceSet)
{
throw new NotImplementedException();
}
public ResourceType GetResourceType(object target)
{
throw new NotImplementedException();
}
public object InvokeServiceOperation(
ServiceOperation serviceOperation,
object[] parameters)
{
throw new NotImplementedException();
}
public bool IsNullPropagationRequired
{
get { throw new NotImplementedException(); }
}
}

We’ve now done the minimum you possible can to get a custom Data Service Provider based Service actually running!

If you browse to your https://localhost/sample.svc now you will see something like this:

ServiceDoc

And this https://localhost/sample.svc/$metadata should look like this:

DollarMetadata

But if you navigate to the Products ResourceSet you will get an error:

Error

That’s because of all those NotImplementedExceptions.

In Part 5 we will flesh out our implementation so query works too...