Solved

Asp.NET Web api logging request and response

Posted on 2016-07-29
10
893 Views
Last Modified: 2016-08-11
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
0
Comment
Question by:Member_2_7967608
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
10 Comments
 
LVL 23

Expert Comment

by:Ioannis Paraskevopoulos
ID: 41735670
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
0
 

Author Comment

by:Member_2_7967608
ID: 41737953
Thanks . This would capture incoming Requests and outgoing Response from Web api?
0
 
LVL 23

Accepted Solution

by:
Ioannis Paraskevopoulos earned 500 total points
ID: 41737998
Yes,

If you see line 29 of the code above SendAsync will send the request to the requested Controller Action and get the response.

This whole method will log the following:

Request Body,
Request Headers,
Response Body,
Response Headers,
Response HTTP Status code

Giannis
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 

Author Comment

by:Member_2_7967608
ID: 41741630
{"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.
0
 

Author Comment

by:Member_2_7967608
ID: 41752079
Can we disable the web api handler or set it in Web.config. I don't want to trace in production.
0
 
LVL 23

Expert Comment

by:Ioannis Paraskevopoulos
ID: 41752099
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
0
 

Author Comment

by:Member_2_7967608
ID: 41752151
Thanks..Yes I still have that issue.
0
 
LVL 23

Expert Comment

by:Ioannis Paraskevopoulos
ID: 41752172
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
0
 

Author Comment

by:Member_2_7967608
ID: 41752935
Thanks
0
 

Author Closing Comment

by:Member_2_7967608
ID: 41752937
Thanks
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question