OData / ODataConnectedService

A Visual Studio extension for generating client code for OData Services
Other
81 stars 44 forks source link

Access to HTTP request body #329

Open szilardd opened 1 year ago

szilardd commented 1 year ago

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:

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

mtherien commented 1 year ago

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();
}