0

When .Net web API returns Badrequest("this is an example of Badrequest".), IOwinContext object in my middleware only contains context.Response.StatusCode 400 and context.Response.ReasonPhrase as "Bad Request". I want actual error message so that I can log it somewhere. Is it possible to get actual error message from IOwinContext without writing any custom class?

EDIT: Startup.cs

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ICoreLogger dv_logger = new CoreLogger();
            app.Use<InvalidAuthenticationMiddleware>(dv_logger);
            ConfigureOAuth(app);
            //register log4net
            XmlConfigurator.Configure();
            // configure log4net variables
            GlobalContext.Properties["processId"] = "dv_logger";
            System.Web.Http.GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            //entity framework
            DbContext.Intialize();
            AuthContext.Intialize();
            .....
   }

Middleware

 public class InvalidAuthenticationMiddleware : OwinMiddleware
{
        public override async Task Invoke(IOwinContext context)
        {
            var stream = context.Response.Body;
            using (var buffer = new MemoryStream())
            {
                context.Response.Body = buffer;
                await Next.Invoke(context);

                buffer.Seek(0, SeekOrigin.Begin);
                using (var reader = new StreamReader(buffer))
                {
                    string responseBody = await reader.ReadToEndAsync();

                    if (context.Response.StatusCode == (int)HttpStatusCode.BadRequest)
                    {
                        var definition = new { Message = "" };
                        var error = JsonConvert.DeserializeAnonymousType(responseBody, definition);

                        Debug.WriteLine(error.Message);
                    }

                    buffer.Seek(0, SeekOrigin.Begin);
                    await buffer.CopyToAsync(stream);
                }
            }
        }

}

Controller

public class LoginController : BaseController
{
        [Route("")]
        public IHttpActionResult Get(string email)
        {
           return BadRequest("this is an example of bad request!");
        }
}
shrey shah
  • 43
  • 5
  • What does `ConfigureOAuth()` do? Why aren't you using `appBuilder.UseWebApi(config)` instead of `GlobalConfiguration.Configure()`? You should simplify your `Startup.Configuration()` and remove some parts to narrow down your problem. – Anouar Jun 04 '20 at 09:36
  • We were using ```appBuilder.UseWebApi(config)``` but we also have a MVC controller in our project. So, we had to switch to ```GlobalConfiguration.Configure()```. ```ConfigureOAuth``` sets property for Owin Authorization. – shrey shah Jun 22 '20 at 14:31

1 Answers1

0

You will have to read the response's body. BadRequest("this is an example of BadRequest") sets an object in the body of the response with a property Message containing that message. I am assuming you are using JSON as a serialization format:

{
    "Message": "this is an example of BadRequest"
}

Here is the middleware code to log the error message when the response is a BadRequest:

public override async Task Invoke(IOwinContext context)
{
    var stream = context.Response.Body;
    using (var buffer = new MemoryStream())
    {
        context.Response.Body = buffer;

        await next.Invoke();

        buffer.Seek(0, SeekOrigin.Begin);
        using (var reader = new StreamReader(buffer))
        {
            string responseBody = await reader.ReadToEndAsync();

            if (context.Response.StatusCode == (int)HttpStatusCode.BadRequest)
            {
                var definition = new { Message = "" };
                var error = JsonConvert.DeserializeAnonymousType(responseBody, definition);

                Console.WriteLine(error.Message);
            }

            buffer.Seek(0, SeekOrigin.Begin);
            await buffer.CopyToAsync(stream);
        }
    }
}

Note that I used an anonymous type to avoid having to declare a class for the error message object.

Anouar
  • 2,050
  • 1
  • 15
  • 25
  • responseBody variable always sets to an empty string if I run above code. Any suggestion? – shrey shah Jun 03 '20 at 14:08
  • How do you register your middleware? Can you include a minimal sample of your code (your controller returning the BadRequest + your startup)? – Anouar Jun 03 '20 at 14:15
  • app.Use(dv_logger); here, InvalidAuthenticationMiddleware contains your code. Controller: return BadRequest("this is an example of bad request!"); – shrey shah Jun 03 '20 at 14:51
  • Don't you have a `app.UseWebApi(config);` also? The order in which you register middlewares is important. Make sure you register your `InvalidAuthenticationMiddleware` before `app.UseWebApi(config);`. In general, the logging middleware has to be registered first. – Anouar Jun 03 '20 at 15:12
  • yes. middleware is registered before ```System.Web.Http.GlobalConfiguration.Configure(WebApiConfig.Register);``` – shrey shah Jun 03 '20 at 15:17
  • I would highly recommend that you update your question to add your example code. Otherwise it would be impossible for me or anyone else to help find your problem cause. – Anouar Jun 03 '20 at 15:22
  • added example code in the question. please look at it. – shrey shah Jun 04 '20 at 05:38