Link to home
Start Free TrialLog in
Avatar of Member_2_7967608
Member_2_7967608

asked on

Asp.NET Web api logging request and response

Hi All

I want to log both JSON request and response made to my web api. Can you show me the standard way of implementing this

Thanks
Adib
Avatar of Ioannis Paraskevopoulos
Ioannis Paraskevopoulos
Flag of Greece image

Hi,

I have created such a solution which logs the messages in a table in the db. Of course you may use whatever logging solution you like.

I am using Ninject for Dependency Injection. In my case DbContext is my DB repository.
For this you need to create a class that will derive from DelegatingHandler. You will need to override SendAsync.

public class LoggingHandler: DelegatingHandler
{
    public DbContext _context {get;set;}
    protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        //Get the _context
        _context = (DbContext)request.GetDependencyScope().GetService(typeof(DbContext));

        //Declare the new Entity
        var logEntity = new Log();
        
        //Read the request body
        var requestMessageBytes = await request.Content.ReadAsByteArrayAsync();

        //Decode the message bytes to string and log them
        logEntity.RequestMessage = Encoding.UTF8.GetString(requestMessageBytes);

        //Log the request Headers
        var requestHeaders = request.Headers.Where(x => x.Value != null && x.Value.Count() > 0);

        var requestHeadersString = String.Empty;
        foreach(var header in request.Headers)
        {
            requestHeadersString += String.Format("{0}: {1}{2}", header.Key, String.Join(", ", header.Value), Environment.NewLine);
        }
        logEntity.RequestHeaders = requestHeadersString;

        //Release the request to the condroller and read the response
        var response = await base.SendAsync(request, cancellationToken);

        //Log the response status
        logEntity.ResponseHTTPStatusCode = response.StatusCode

        //Log the response body
        byte[] responseMessageBytes;

        if(response.Content != null)
        {
            responseMessage = await response.Content.ReadAsByteArrayAsync();
        }

        logEntity.ResponseBody = Encoding.UTF8.GetString(responseMessage);


       //Log the Response Headers
        var responseHeaders = response.Headers

        var responseHeadersString = String.Empty
        foreach(var header in response.Headers)
        {
            responseHeadersString += String.Format("{0}: {1}{2}", header.Key, String.Join(", ", header.Value), Environment.NewLine);
        }

        logEntity.ResponseHeaders = requestHeadersString;


       //Save the entry
        _context.Entities.Log.Add(logEntity);
        _context.SaveChanges();

    }

}

Open in new window


Now you need to register this so it takes effect. What i do for this is put the following in Global.asax Application_Start :

        GlobalConfiguration.Configuration.MessageHandlers.Add(New LoggingHandler())

Open in new window


Please make note that in my case i was using VB.Net, so i had to transform the code to C# for you. This means that i have not really tested this exact implementation but i guess it will. Let me know how it goes.

Giannis
Avatar of Member_2_7967608
Member_2_7967608

ASKER

Thanks . This would capture incoming Requests and outgoing Response from Web api?
ASKER CERTIFIED SOLUTION
Avatar of Ioannis Paraskevopoulos
Ioannis Paraskevopoulos
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
{"RequestMessage":"{\r\n  \"BID\" : \"1\",\r\n  \"EID\": \"2\",\r\n  \"TD\": \"3\",\r\n  \"SID\": \"4\",\r\n  \"ID\": \"5\",\r\n  \"Key\": \"93b\"\r\n}","RequestHeaders...................................

I am able to log. But I am getting  \r\n   or \  in the    logged request and response. Can we get rid of it.
Can we disable the web api handler or set it in Web.config. I don't want to trace in production.
Hi,

If you want to set it in the web.config then you could do it like this:

In web.config:

 <appSettings>
...
    <add key="EnableLogging" value="true" />
...
 </appSettings>

Open in new window


In Global.asax Application_Start :

if(ConfigurationManager.AppSettings["EnableLogging"] == "true")
{
    GlobalConfiguration.Configuration.MessageHandlers.Add(New LoggingHandler())
}

Open in new window


Another way without the web.config change would be:


In Global.asax Application_Start :

#if DEBUG
    GlobalConfiguration.Configuration.MessageHandlers.Add(New LoggingHandler())
#endif

Open in new window


I prefer the first way though ;-).

By the way, i missed your other question on how to get rid of the \r\n s etc. Do you still have a problem with that?

Giannis
Thanks..Yes I still have that issue.
Well you may try this:

var escapedString = "{\r\n  \"SomeResponse\":\r\n  {\r\n    \"FIrstAttribute\":8,\r\n    \"SecondAttribute\":\"On\"\r\n  }\r\n}";
var result = System.Text.RegularExpressions.Regex.Unescape(escapedString);

Open in new window


Giannis
Thanks
Thanks