Question

To begin with two things.

  1. I am trying to achieve an action filter that logs when and action begins and when it end
  2. I am well aware of the .AsActionFilter() method in Autofac 3.0 BUT...

The project that this is using is based in Orchard 1.6 which is known to be compatible with autofac 2.6.xxx. We do not want to go through a potentially lengthy process of upgrading to Autofac 3.0 at this time so the .AsActionFilter() option is not available to us.

The other option is to set the filter (which extends ActionFilterAttribute) as an attribute on our base controller (from which all other inherit btw). The problem is that the filter itself has two dependencies:

  1. A service of our own that holds information on the context
  2. An implementation of an ILoggingService

What I cannot find is a way to inject these into the actual property at the head of the class. Does anyone know a way in which to achieve this either through the [Attribute] line itself of some function of Autofac during registation?

The ActionFilterAttribute:

public class GRMSActionLoggingFilter : ActionFilterAttribute {
    private readonly IGRMSCoreServices _grmsCoreServices;
    private readonly ILoggingService _loggingService;

    public GRMSActionLoggingFilter(IGRMSCoreServices grmsCoreServices, ILoggingService loggingService) {
        _grmsCoreServices = grmsCoreServices;
        _loggingService = loggingService;
    }

    public GRMSActionLoggingFilter() { }

    public override void OnActionExecuting(ActionExecutingContext actionContext) {...}
    public override void OnActionExecuted(ActionExecutedContext actionContext) {...}
}

Assigning the attribute to the base controller:

// This currently compiles but will fail during run time as the IGRMSCoreSerivces and ILoggingService will both be null. Need to property inject these services somehow. 
[GRMSActionLoggingFilter]

Anyone have any idea to achieve this?

Was it helpful?

Solution

You cannot (easily) inject runtime values to attributes. This is how attributes work in C# - you can only pass constant values of certain types. You can read more about it here.

In order to achieve desired functionality in Orchard you need to split your code into two components:

  • a marker attribute class you put on your action
  • an action filter class inheriting from FilterProvider and implementing IActionFilter

The way it works is that you put an attribute on some action and then use the action filter to check existence of that attribute (using filterContext.ActionDescriptor.GetCustomAttributes(...)). If an attribute exists, do your stuff.

There are lots of examples of this technique in Orchard core. Check eg. the ThemedAttribute and ThemeFilter action filter classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top