David Dworetzky David Dworetzky - 3 months ago 36
C# Question

Creating a custom Delegating handler

I'm looking to add a custom delegating handler to my asp.net web api. The purpose of this handler would be to inspect the contents of my requests and validate them for certain conditions before they continue on in the request pipeline... I would also want to log out the requests at this entry point.

However, the request.content that is being passed in the pipeline is a system.web.http.webhost.httpcontrollerhandler.lazystreamcontent - which looking up this type in MSDN reveals nothing about how to deserialize or view the request contents - when I try to read the contents from a stream, I'm left with an empty string. see example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace Haxy.Pencilthis.Api.MVC.Handlers
{
public class ContentValidationHandler : DelegatingHandler
{

private static log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
Stream strea = new MemoryStream();
request.Content.CopyToAsync(strea);
StreamReader reader = new StreamReader(strea);
String res = reader.ReadToEnd();
Log.Info("request content: " + res);
return base.SendAsync(request, cancellationToken);

//
}

}
}

Answer

The reason nothing was being returned to res was that the stream position was set to the end of the Request content, not the beginning. Also, the response was faulting because the base.SendAsync method was not being properly awaited.

Proper implementation below:

public class ContentValidationHandler : DelegatingHandler
{

    private static log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {

        var response = await base.SendAsync(request, cancellationToken);


        Stream strea = new MemoryStream();
        await request.Content.CopyToAsync(strea);
        strea.Position = 0;
        StreamReader reader = new StreamReader(strea);
        String res = reader.ReadToEnd();
        Log.Info("request content: " + res);

        return response;







        //
    }





}