?
Solved

Asp.NET Web api logging request and response

Posted on 2016-07-29
10
Medium Priority
?
1,196 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 2000 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

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

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses

770 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