4

I am looking to create a filter implementing IAsyncActionFilter that will retrieve data from the current request's context's ActionParameters and its Result. I'm using a custom attribute MyLogAttribute to direct the logging beheavior, e.g. to opt-in for logging and indicating fields with critical information.

public class AsyncMyLogFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        if (actionDescriptor != null)
        {
            var attribute = actionDescriptor.MethodInfo.GetCustomAttribute<MyLogAttribute>();

            if (attribute != null)
            {

                await next();

                // This is where the magic is supposed to happen:
                LoggerHelper.Log(context.ActionArguments, context.Result);
            }

            return;
        }

        await next();
    }
}

The way the filter provides a next() delegate led me to believe that past that point the action would be completed and the result object available for inspection as an ObjectResult. However, while the filter is able to grab the ActionArguments without problem, the Result property is unfortunately just null, which is not helpful at all.

The obvious alternative, the synchronous IActionFilter, lets me examine the Result object on the OnActionExecuted stage, but at this point the ActionArguments dictionary is not available.

So, is there any way to access both ActionArguments and Result within the same method scope?

-S

2
  • Are the arguments not available on ActionExecutedContext.ActionDescriptor.Parameters? Commented Sep 14, 2017 at 12:30
  • The Parameters collection includes the names and types of the parameters, but does not appear to hold their values. Commented Sep 15, 2017 at 8:01

2 Answers 2

5

The result of next() will be the result context.

This code sample is from the Filters documentation

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;

    namespace FiltersSample.Filters
    {
        public class SampleAsyncActionFilter : IAsyncActionFilter
        {
            public async Task OnActionExecutionAsync(
                ActionExecutingContext context,
                ActionExecutionDelegate next)
            {
                // do something before the action executes
                var resultContext = await next();
                // do something after the action executes; resultContext.Result will be set
            }
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

1

While the problem in its original form has not been resolved, I was able to create a workaround with an IActionFilter:

public class ActivityLogFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

        if (actionDescriptor != null)
        {
            var attribute = actionDescriptor.MethodInfo.GetCustomAttribute<MyLogAttribute>();

            if (attribute != null)
            {
                context.HttpContext.Items["MyLogData"] = GetRelevantLogData(context.ActionArguments); // Apply some custom logic to select relevant log data
            }
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

            if (actionDescriptor != null)
            {
                var attribute = actionDescriptor.MethodInfo.GetCustomAttribute<MyLogAttribute>();

                if (attribute != null)
                {
                    var actionParametersData = (MyActionParametersLogData)context.HttpContext.Items["MyLogData"]

                    LoggerHelper.Log(actionParametersData, context.Result);
                }
            }
        }
    }
}

Not exactly rocket science; it looks kinda flimsy ("What if my HttpContext items go missing!?"), but it seems to do the job.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.