I'm using WebApi
. I have a custom ActionFilter
on my base controller and a custom ExceptionFilter
added globally. Both are inherited from the associated FilterAttributes in the System.Web.Http.Filters
namespace, not the mvc versions.
I've been getting an exception thrown from a private method within one of my services, this method is what resharper calls a method group, when it's used within a Linq statement (in this case a select
).
public IEnumerable<Foo> GetFoos()
{
IEnumerable<Bar> bars = _work.BarRepository.GetAll();
//throw new Exception("I'm visible to the filters");
IEnumerable<Foo> foos = bars.Select(MakeFooFromBar);
return foos;
}
private Foo MakeFooFromBar(Bar bar)
{
// an exception is being thrown here
// which is not being caught by the filers
throw new Exception("I am invisible to the filters");
}
This exception is not being caught by either filter (see filters below). My action filter says there was no exception and my exception filter is never hit. If I throw an exception prior to the Linq select (the one I've commented out), then the exception is caught as expected.
Using fiddler, what I end up with is this:
{
"message":"An error has occurred.",
"exceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
"exceptionType":"System.InvalidOperationException",
"stackTrace":null,
"innerException":{
"message":"An error has occurred.",
"exceptionMessage":"I am invisible to the filters",
"exceptionType":"System.Exception",
"stackTrace":""
}
}
A portion of my action filter:
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
Exception exception = actionExecutedContext.Exception;
if (exception == null)
{
// do things
}
else
{
// do some other things
}
}
and a portion of my exception filter:
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
// return early on certain kinds of exceptions...
_loggedErrorService.Log(actionExecutedContext.Exception);
}
From the documentation
The problem is that if you return an
IEnumerable<T>
from your WebAPI method, the error will occur during serialization, when theIEnumerable<T>
is iterated. This is the standard behavior ofSelect
(and most other query operators) it only call the method passed to it upon iteration (MakeFooFromBar
in this case), so the exception will not be thrown when you invokeSelect
but much later.You could add a
.ToList
to cause the exception to occur inside your method.