8

Im currently developing an MVC application in ASP.NET and I'm trying to separate concerns so that I end up with cleaner and more maintanable code.

So, as a starting point, I was thinking of a logging aspect. My idea is to log (initially) the calling and returning of every method in every controller. I would have this logic on a separate class, dedicated to logging, so I don't mess my code with logging statements everywhere.

I would also need to have access to the Http Request so I can obtain client information.

Is there an integrated way to do this? Can ASP.NET MVC be used with aspect files just like AspectJ in Java?

Also, can it later be configured to log methods that satisfies certain conditions? (like signature, returning value, exception throwing, etc.)

Thanks very much in advance!

Matias Cicero
  • 25,439
  • 13
  • 82
  • 154

1 Answers1

12

You can use attributes to implement a feature in an aspect-oriented way. Action methods that you want to surround with your functionality then only need to be decorated with your attribute:

[CustomLogger]
public ActionResult Index()
{
    // Doing something here ...
    return View();
}

You can either decorate a single action method with an attribute, an entire controller, or even apply the attribute globally through ASP.NET MVC's GlobalFilterCollection.

Here's how you'd declare your attribute:

public class CustomLoggerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        // Here goes your logic
    }

    // ...
}

The ActionFilterAttribute class allows you to override a couple of methods so you can hook into ASP.NET MVC's action execution pipeline:

  • OnActionExecuting
  • OnActionExecuted
  • OnResultExecuting
  • OnResultExecuted

You can access request variables through the parameters (like ActionExecutedContext) that are passed to the above methods.

Marius Schulz
  • 15,976
  • 12
  • 63
  • 97
  • This is interesting, can it be used at Controller level? I mean, annotating the class so that it applies to all actions of that controller automatically. Even if that's the case though, I am not fond of the idea to annotate my controllers, I was thinking of a more transparent way, so that controllers and the logging aspect are totally independent. The controller should not know if it is being logged or not. – Matias Cicero Apr 23 '14 at 12:45
  • 2
    @MatiCicero Now you were faster than I was. ;-) Yeah, you can scope the attribute to a single action method, an entire controller, or every controller in an ASP.NET MVC application. That way, not a single controller needs to know about the attribute — only `GlobalFilterCollection.Filters` is used; also, you can't forget to apply an attribute to a certain controller, which is great for authentication / authorization purposes. – Marius Schulz Apr 23 '14 at 12:47
  • Ok, now we are talking @Marius Schulz!! I am liking this idea, can it be used to not to log all the actions, but just certain ones that satisfies some signature? I am thinking of using reflection maybe, but if there's an automated way of doing this I'm all ears! – Matias Cicero Apr 23 '14 at 12:49
  • @MatiCicero That's possible, yes. The supplied `filterContext` variable contains a property of type `ActionDescriptor` which provides information about the signature, parameters, etc. – Marius Schulz Apr 23 '14 at 12:51
  • I guess this approach covers everything I need then, I am going to try this and come back with news, I will mark this as an accepted answer! Thank you! – Matias Cicero Apr 23 '14 at 12:55
  • 1
    @Mati Cicero, How did you feel in the end with using this approach? Did you try any AOP libraries? Have you stuck with this method or since changed your mind? – puddinman13 Mar 27 '15 at 16:33