ODataConnectedService icon indicating copy to clipboard operation
ODataConnectedService copied to clipboard

Access to HTTP request body

Open szilardd opened this issue 3 years ago • 1 comments

Is there a way to access the underlying HTTP request body to log requests?

For example, when doing an update, the underlying HTTP request looks something like this:

PATCH https://mydomain.com/data/myentity(OrderId='id1')
Content-Type: application/json
Authorization: Bearer {{token}}

{ "Quantity": 2, "Type": "Internal" }

I would like to access the request body ({ "Quantity": 2, "Type": "Internal" }) for logging/debugging purposes.

Describe the solution you'd like

Maybe include a RequestBody property in the dataServiceContext.BuildingRequest event? Or a different event?

Describe alternatives you've considered

I looked into all of the events generated in the data context class:

  • dataServiceContext.SendingRequest2
  • dataServiceContext.BuildingRequest
  • dataServiceContext.ReceivingResponse
  • dataServiceContext.Configurations.RequestPipeline.OnMessageCreating

These are very useful but I can only access the HTTP Headers for the request and the response and the response body. The only missing is the request body.

The BuildingRequest event seems to contain the required info, but it's not accessible publicly:

var dataServiceContext = new MyDataContext(new Uri("https://mydomain.com/data"));

dataServiceContext.BuildingRequest += (object sender, BuildingRequestEventArgs e) =>
{
    var descriptor = ((EntityDescriptor)e.Descriptor);
    var entity = descriptor.Entity;

    descriptor.PropertiesToSerialize // can't access because it is internal only
};

When debugging you can see that PropertiesToSerialize contains the fields that will be serialized and it could be used to retrieve the field values from the Entity property using reflection, but the problem is that PropertiesToSerialize is internal. See screenshot

image

szilardd avatar Dec 14 '22 07:12 szilardd

I too would like to see this. I have implemented a workaround. It doesn't do exactly what you need but it is something...

DataServiceContext.Configurations.RequestPipeline.OnEntryEnding((arg) =>
{
        var jsonObject = new JObject();

        foreach (var property in arg.Entry.Properties)
        {
            if (property.Value != null)
            {
                if (property.Value.GetType().IsEnum)
                {
                    jsonObject.Add(property.Name, property.Value.ToString());
                }
                else
                {
                    jsonObject.Add(property.Name, JToken.FromObject(property.Value));
                }
            }
        }

        var jsonString = jsonObject.ToString();
}

mtherien avatar Dec 14 '22 14:12 mtherien