Solved

Asp.NET Web api logging request and response

Posted on 2016-07-29
10
581 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
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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

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

Suggested Solutions

Title # Comments Views Activity
asp web application 3 40
Dictionary and array of [N] size - performance tuned 12 41
Query in AngularJS 8 46
Header Font Size in Grid View 6 25
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.
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled

749 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