Web API global error handling add custom header in response - c#

I was wondering if it was possible to set some custom header values whenever an internal server error has occurred? I am currently doing:
public class FooExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
// context.Result already contains my custom header values
context.Result = new InternalServerErrorResult(context.Request);
}
}
Here I also want to set some header values but though it appears in the request the response does not contain it.
Is there a way of doing this?

There is a sample code for your reference, my ApiExceptionHandler is your
FooExceptionHandler
public class ApiExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var response = new Response<string>
{
Code = StatusCode.Exception,
Message = $#"{context.Exception.Message},{context.Exception.StackTrace}"
};
context.Result = new CustomeErrorResult
{
Request = context.ExceptionContext.Request,
Content = JsonConvert.SerializeObject(response),
};
}
}
internal class CustomeErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response =
new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(Content),
RequestMessage = Request
};
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Headers", "*");
return Task.FromResult(response);
}
}

It should be possible by creating your own exception filter.
namespace MyApplication.Filters
{
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
public class CustomHeadersFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
context.Response.Content.Headers.Add("X-CustomHeader", "whatever...");
}
}
}
http://www.asp.net/web-api/overview/error-handling/exception-handling

Related

How can I return a JSON object and status code (IHttpActionResult) from an ExceptionHandler in Web API?

Normally, I'd just do in my controller action:
return Content(System.Net.HttpStatusCode.InternalServerError,
new MyCustomObject("An error has occurred processing your request.", // Custom object, serialised to JSON automatically by the web api service
ex.ToString()));`
However the Content method exists on the controller. The ExceptionHandler I made has this:
public override void Handle(ExceptionHandlerContext context)
{
context.Result = ???;
The type of context.Result is IHttpActionResult, so what I need to do is create one and stick it in there. I can't find any constructors or similar that will allow me to create an IHttpActionResult outside of a controller. Is there an easy way?
I thing for custom responses you should probably implement your own http action result:
public override void Handle(ExceptionHandlerContext context)
{
context.Result = new HttpContentResult(new { }, context.Request);
}
public class HttpContentResult : IHttpActionResult
{
private readonly object content;
private readonly HttpRequestMessage requestMessage;
public HttpContentResult(object content, HttpRequestMessage requestMessage)
{
this.content = content;
this.requestMessage = requestMessage;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var httpContentResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);
var httpContent = new StringContent(content);
//... [customize http contetnt properties]
httpContentResponse.Content = httpContent;
httpContentResponse.RequestMessage = this.requestMessage;
//... [customize another http response properties]
return Task.FromResult(httpContentResponse);
}
}

Blazor Post and Response C#

Having an issue posting from client to server in a server-side Blazor webapp.
I've created two simple classes in a shared library:
public class CommandRequest
{
public int RequestNumber { get; set; }
}
public class CommandResponse
{
public int ResponseNumber { get; set; }
}
My client side code:
#if (response == null)
{
<p>Loading...</p>
}
else
{
<p>#response.ResponseNumber</p>
}
#functions {
CommandResponse response;
protected override async Task OnInitAsync()
{
var request = new CommandRequest() {RequestNumber = 3};
response = await Http.SendJsonAsync<CommandResponse>(HttpMethod.Post,"api/SampleData/ProcessRequest", request);
}
}
My server side request handler:
[HttpPost("[action]")]
public CommandResponse ProcessRequest(CommandRequest request)
{
return new CommandResponse() { ResponseNumber = request.RequestNumber * 2 };
}
When I debug this the ProcessRequest method is always passed an empty object, request.RequestNumber is 0. I'm new to ASP.NET and Blazor, what am I doing wrong?
Adding [FromBody] attribute to the CommandRequest parameter solved my problem:
[HttpPost("[action]")]
public CommandResponse ProcessRequest([FromBody] CommandRequest request)
{
return new CommandResponse() { ResponseNumber = request.RequestNumber * 2 };
}
A reference here:
What is the function of [FromBody] Attribute in C#?

Exception handler doesn't catch exceptions

I have two projects in one solution. The 1st it's library project and the second it's Asp.Net WebApi project. Both using .Net Framework 4.6.1.
I want to make some class that will handling exceptions globally. I found nice solution using ExceptionHandler, however it doesn't work as I expected. I was following this article https://learn.microsoft.com/pl-pl/aspnet/web-api/overview/error-handling/web-api-global-error-handling.
Here is my class where I handle exceptions.
public class GlobalExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = context.Exception.Message
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response =
new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
For instance I have this code in my library project.
public class ThrowSomething
{
public void ThrowSomeException()
{
throw new Exception("Custom exception");
}
}
And in my controller in Asp.Net I have
public IHttpActionResult SomeAction()
{
var throwSomething = new ThrowSomething();
throwSomething.ThrowSomeException();
return Ok();
}
I would like to catch the exception in my GlobalExceptionHandler class and return some result to the Api. Currently the GlobalExceptionHandler is not handling the exceptions.
I also have config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); in Register method in WebApiConfig.

Global Exception Handling Web Api 2

I am trying to figure out how to implement a Global Exception Handler in .NET Web Api 2.
I tried following the example set out by Microsoft here:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/web-api-global-error-handling
But when exception occured, it did nothing.
This is my code:
public class GlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
Trace.WriteLine(context.Exception.Message);
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong." +
"Please contact support#testme.com so we can try to fix it."
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { private get; set; }
public string Content { private get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response =
new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(Content),
RequestMessage = Request
};
return Task.FromResult(response);
}
}
}
Is there a better way (or more proper way) to implement a global exception handler?
Try adding this to your WebApiConfig
webConfiguration.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler()); // You have to use Replace() because only one handler is supported
webConfiguration.Services.Add(typeof(IExceptionLogger), new MyExceptionLogger()); // webConfiguration is an instance of System.Web.Http.HttpConfiguration
You missed
class GlobalExceptionHandler : ExceptionHandler
{
public override bool ShouldHandle(ExceptionHandlerContext context)
{
return true;
}
//...
}
See WebApi v2 ExceptionHandler not called

using global exception handeling messes up DelegatingHandler

When ovveride the IExceptionHandler, the response does not reach the DelegatingHandler when a unexpected exception occurs. How can I fix this?
In webapi 2, I want to implement a audit logger for request and response messages. I also want to add a global exception handler. However, when I replace the IExceptionHandler with my custom implementation. the response never reaches the DelegatingHandler -on exception - And thus the audit for response is lost.
in WebApiConfig
// add custom audittrail logger
config.MessageHandlers.Add(new AuditLogHandler());
// replace global exception handeling
config.Services.Replace(typeof(IExceptionHandler), new WebAPiExceptionHandler());
Custom Exception Handler
public class WebAPiExceptionHandler : ExceptionHandler
{
//A basic DTO to return back to the caller with data about the error
private class ErrorInformation
{
public string Message { get; set; }
public DateTime ErrorDate { get; set; }
}
public override void Handle(ExceptionHandlerContext context)
{
context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError,
new ErrorInformation { Message = "Iets is misgegaan", ErrorDate = DateTime.UtcNow }));
}
}
Custom Auditlogger
public class AuditLogHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content != null)
{
var task = await request.Content.ReadAsStringAsync();
// .. code for loggign request
}
var result = await base.SendAsync(request, cancellationToken);
// .. code for logging response
// when I do not replace WebAPiExceptionHandler, code is reachred here
// When I Do use WebAPiExceptionHandler, code is not reached here
return result;
}
}
Code for throwing exception in webapi
public class Values_v2Controller : ApiController
{
public string Get(int id)
{
throw new Exception("haha");
}
}
Dont use ExceptionHandler as base class, implement interface IExceptionHandler
public class WebAPiExceptionHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var fout = new ErrorInformation
{
Message = "Iets is misgegaan"
, ErrorDate = DateTime.UtcNow
};
var httpResponse = context.Request.CreateResponse(HttpStatusCode.InternalServerError, fout);
context.Result = new ResponseMessageResult(httpResponse);
return Task.FromResult(0);
}
private class ErrorInformation
{
public string Message { get; set; }
public DateTime ErrorDate { get; set; }
}
}
The problem is that ExceptionHandler only executes Handle(ExceptionHandlerContext context) method if ShouldHandle(ExceptionHandlerContext context) returns true.
Overriding bool ShouldHandle(ExceptionHandlerContext context) to always return true fix the problem for me.

Categories

Resources