in src/Microsoft.Azure.WebJobs.Host/Executors/FunctionExecutor.cs [1103:1168]
public async Task<object> InvokeAsync(object instance, object[] arguments)
{
// Invoke the filter pipeline.
// Basic rules:
// - Iff a Pre filter runs, then run the corresponding post.
// - if a pre-filter fails, short circuit the pipeline. Skip the remaining pre-filters and body.
CancellationToken cancellationToken;
int len = _filters.Count;
int highestSuccessfulFilter = -1;
Exception exception = null;
var properties = _parameterHelper.FilterContextProperties;
FunctionExecutingContext executingContext = new FunctionExecutingContext(_parameterHelper.GetParametersAsDictionary(), properties, _functionInstance.Id, _functionInstance.FunctionDescriptor.ShortName, _logger);
try
{
for (int i = 0; i < len; i++)
{
var filter = _filters[i];
await filter.OnExecutingAsync(executingContext, cancellationToken);
highestSuccessfulFilter = i;
}
var result = await _innerInvoker.InvokeAsync(instance, arguments);
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
var functionResult = exception != null ?
new FunctionResult(exception)
: new FunctionResult(true);
FunctionExecutedContext executedContext = new FunctionExecutedContext(_parameterHelper.GetParametersAsDictionary(), properties, _functionInstance.Id, _functionInstance.FunctionDescriptor.ShortName, _logger, functionResult);
// Run post filters in reverse order.
// Only run the post if the corresponding pre executed successfully.
for (int i = highestSuccessfulFilter; i >= 0; i--)
{
var filter = _filters[i];
try
{
await filter.OnExecutedAsync(executedContext, cancellationToken);
}
catch (Exception e)
{
exception = e;
executedContext.FunctionResult = new FunctionResult(exception);
}
}
// last exception wins.
// If the body threw, then the finally will automatically rethrow that.
// If a post-filter throws, capture that
if (exception != null)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
}
}