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.
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>(); } }
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:
And this http://localhost/sample.svc/$metadata should look like this:
But if you navigate to the Products ResourceSet you will get an error:
That’s because of all those NotImplementedExceptions.
In Part 5 we will flesh out our implementation so query works too...