Determining if a Service is OData compliant
The OData specification was originally described by the Microsoft corporation under the Microsoft Open Specification Promise. However, compliance to a standard can be subjective and may mean that not all services are fully compliant or contain errors in their structure. Due to this, the K2 OData Service Broker may display unexpected behavior if the service is not fully OData compliant. The steps in this topic explain how to test an OData service for compliance before attempting to register an OData Service Instance or generating and using SmartObjects based on the service. .
The steps described here also aid when trying to determine whether a problem resides with the OData service itself or with the OData service broker.
Apart from the steps below, also see http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/calling-an-odata-service-from-a-net-client for more resources on testing OData compliance.
The full OData specification can be found at http://www.odata.org/documentation/odata-version-3-0/. This external page is liable to change over time however, so you may need to search the site to find the documents describing the complete OData spec
Required Resources
- Visual Studio (a console application will be used to determine if the service is OData compliant)
- The OData service URL of the service you intend to test
If you wish to test this approach with a known, working service, paste the following URL into the browser of your choice:
http://services.odata.org/V3/(S(readwrite))/OData/OData.svc/
This will generate a sample “readwrite” OData service that you can use for testing this approach.
Results in the following sample service URL:
Testing the Service
To get started, you need to create a Service Reference within your project. Create a Visual Studio Console Application, naming it for example ‘OData Test Service’.Once your project is up and running, follow the steps below:
- From the Project Explorer, right on click on References and select Add Service Reference
- The Add Service Reference dialog appears
- Enter the OData service URL into the field labelled Address
- Enter a Namespace name for example: ODataService
- Click Go
- There may be a delay as the data is downloaded, should it be successful you will be able to view the Services in the tree view labelled Services. Click OK to complete.
- If successful, the project explorer will update as shown below:
- Add the following references to you project
- System.Net
- Namespace + Service Name ie: TestODataService.ODataService
- The goal from this point forward is to determine the level of compliance your service has with OData. If you’ve successfully made it to this step then some major hurdles have already been cleared. They include having a $metadata document available and having entities which ALL have primary keys among others.
- Next you will need to write some code to verify that the service can perform the operations you wish to expose. The code will depend on the service you intend to consume. The code sample below illustrates testing the generic OData service URL described in the required resources section.
class Program {
static void Main(string[] args) {
DemoService demoService = new DemoService(new Uri("http://services.odata.org/V3/(S(jtqzg2omvsfijmswesaplibf))/OData/OData.svc/"));
//Fill this property in with your relevant credentials.
demoService.Credentials = CredentialCache.DefaultNetworkCredentials;
//Test listing on entities
var products = demoService.Products.ToList();
var categories = demoService.Categories.ToList();
var suppliers = demoService.Suppliers.ToList();
//etc....
//Test loading an entity
var product5 = demoService.Products.Where(x => x.ID == 5).FirstOrDefault();
//Test updating an entity
product5.Name = "UpdatedTestProduct";
demoService.UpdateObject(product5);
demoService.SaveChanges();
//Test creating an entity
Product newProduct = new Product() {
ID = 253,
//The primary key(s) of the entity must always be set
//(in this case the key is the ID property)
Name = "NewTestProduct",
Description = "Testing",
Rating = 8
/* etc... */
};
//For inherited types use the BaseType
//(e.g. when testing the inherited entity DemoService.FeaturedProduct, use
//typeof(DataServiceQuery<Product>) as shown)
var productsQueryType = typeof(DataServiceQuery < Product > );
var entitySetName = typeof(DemoService).GetProperties().Where(x => x.PropertyType == productsQueryType).FirstOrDefault().Name;
demoService.AddObject(entitySetName, newProduct);
demoService.SaveChanges();
}
}
}
- The above program can be modified to test any OData service that isn’t behind a client certificate or that requires OAuth. Should any of the operations fail, then there are a few things to check.
- First, make sure your service allows full access to each entity. It’s perfectly acceptable to allow reads but not writes and vice-versa.
- Services can also restrict the number of records you can pull on each request, so the entire entityset may not come back when listing. Filtering or paging code would need to be written in this sample to overcome this. The OData service broker accommodates this.
- Another source of strange behavior could be an attached resource stream on the entity. If this is the case then the error should be fairly clear and indicate that no media or named resource stream was set.
- Bad credentials could also be a source of issues. If your service needs more advanced authentication such as OAuth or an X.509 client certificate, then additional code would need to be written into the sample above. For OAuth you can set the Bearer token in the headers by adding to the SendingRequest2 event on the DataServiceContext (DemoService class in this example). For X.509 certificates the code necessary to test with them is outside of the scope of this document. It involves compiling a dll at runtime using the EntityClassGenerator.
- If all the points in step 8 have been checked but you still experience trouble. then there is a strong likelihood that your service is not OData compliant in some way. To determine the exact way in which your service is not compliant, you will need to consult the OData spec.