Question

I am developing a .Net client to retrieve data from an oData service. My client uses a System.Data.Services.Client.DataServiceContext.

I would like to see the actual oData requests sent out to the server. The server uses an SSL connection and requests to the server cannot easily be sniffed. I tried to do this with Burp. I added a SendingRequest EventHandler and set the Request.Proxy property. But this gives an exception:

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

Wireshark just shows the encrypted data.

Alternatively, I could contact the oData provider for server logs, but that would take some time. I am looking for a instantaneous trace.


Here is a sample client, that uses the Microsoft Northwind oData service.

  1. Create a Class Library;
  2. Add a Service Reference to Northwind;
  3. Create a class oDataClient;
  4. Add a method Customers();
  5. Create a Test project;
  6. Create in it a unit test for Customers();
  7. Run the test.

Method:

public class oDataClient
{
    public void Customers()
    {
        {
            var context = new Northwind.NorthwindEntities(new System.Uri("http://services.odata.org/V3/Northwind/Northwind.svc/"));

            var customers = from c in context.Customers 
                            where c.CompanyName.StartsWith("A")
                            select c;

            int count = customers.Count();
        }
    }
}

Test:

[TestMethod()]
public void CustomersTest()
{
    oDataClient target = new oDataClient();
    target.Customers();
}
Was it helpful?

Solution

You can use the SendingRequest2, ReceivingResponse event to trace the out going OData request in client side. see the below example for more detail.

using Microsoft.OData.Client;
using Simple.OData.Client;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ODataClientApp
{
    class Program
    {
        private static string fileName = "TraceLog.log";
        private static Default.Container container;
        static void Main(string[] args)
        {
            try
            {
                var uri = "http://localhost:32097/odata";
                container = new Default.Container(new Uri(uri));

                container.SendingRequest2 += Container_SendingRequest2;
                container.ReceivingResponse += Container_ReceivingResponse;
                var moviles = container.Movies.Execute().ToList();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
        }

        private static void Container_SendingRequest2(object sender, Microsoft.OData.Client.SendingRequest2EventArgs e)
        {
            var request = e.RequestMessage as HttpWebRequestMessage;
            var x = container;
            var url = request.Url.AbsoluteUri;
            var method = request.Method;
            var authenticationLevel = request.HttpWebRequest.AuthenticationLevel;
            var impersonationLevel = request.HttpWebRequest.ImpersonationLevel.ToString();
            var headers = request.Headers;
            var sb = new StringBuilder();
            sb.AppendLine(DateTime.Now.ToString() + "------------------------------SendingRequest2 Begin---------------------------");
            sb.AppendLine("Url:" + url);
            sb.AppendLine("Method:" + method);
            sb.AppendLine("Authentication Level:" + authenticationLevel);
            sb.AppendLine("Impersonation Level:" + impersonationLevel);
            sb.AppendLine();
            sb.AppendLine("Header Info:-");
            foreach (var header in headers)
            {
                sb.AppendFormat("{0}:{1}", header.Key, header.Value);
                sb.AppendLine();
            }
            sb.AppendLine(DateTime.Now.ToString() + "------------------------------SendingRequest2 End-----------------------------");
            File.AppendAllText(fileName, sb.ToString());
        }
        private static void Container_ReceivingResponse(object sender, Microsoft.OData.Client.ReceivingResponseEventArgs e)
        {
            var response = e.ResponseMessage as HttpWebResponseMessage;
            var statusCode = response.StatusCode.ToString();
            var headers = response.Headers;

            var sb = new StringBuilder();
            sb.AppendLine(DateTime.Now.ToString() + "------------------------------ReceivingResponse Begin-------------------------");
            sb.AppendLine("Status Code:" + statusCode);
            sb.AppendLine();
            sb.AppendLine("Header Info:-");
            foreach (var header in headers)
            {
                sb.AppendFormat("{0}:{1}", header.Key, header.Value);
                sb.AppendLine();
            }
            sb.AppendLine(DateTime.Now.ToString() + "------------------------------ReceivingResponse End---------------------------");
            File.AppendAllText(fileName, sb.ToString());
        }
    }
}

OTHER TIPS

While writing down this question and creating the sample client, I suddenly noticed that the actual request submitted to the server is not hidden deep down in the .Net libraries, but can easily be watched!

If you run the test and step through the code, after the context is queried, the object customers just simply shows the url. In this case:

http://services.odata.org/V3/Northwind/Northwind.svc/Customers()?$filter=startswith(CompanyName,'A') 

which is actually the RequestUri property of the underlying base class DataServiceQuery instance.

So, I hope this answer is useful for anyone overlooking this just like me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top