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 http://localhost/sample.svc now you will see something like this:

ServiceDoc

And this http://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...