28

Is there A good strategy to Log the User activity on an ASP MVC App? (ActionFilters/ HTTPModules).

Something like last user activity (just like StackOverflow "Seen 23 mins ago"), and even what Pages and Controllers were used, and pushing even further what buttons or links were clicked.

I have ELMAH installed but as far as i know its just for Error Logging.

PD: Google Analytics is not an option.

4 Answers 4

49

Warning: This was written in 2009 for MVC .NET RC1 and may not be syntactically correct anymore.

Action Filter Attributes are perfect for this, just put a call to [YourAttributeName] at the top of your controller (or if you have an Application Controller which your other controllers inherit from, you only need it once in your application).

For example:

namespace the_name_space
{
    [Log]
    public class ApplicationController : Controller
    {

From this point onwards this attribute will be called before each action is run in your controller(s), you can also specify this on just an action by calling [Log] just before it in the same fashion.

To get the logging functionality which you require, you will most likely want to override OnResultExecuting and OnResultExecuted, both of which are pretty self explanatory.

For example:

public class LogAttribute : ActionFilterAttribute
{
    protected DateTime start_time;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        start_time = DateTime.Now;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        RouteData route_data = filterContext.RouteData;
        TimeSpan duration = (DateTime.Now - start_time);
        string controller = (string)route_data.Values["controller"];
        string action = (string)route_data.Values["action"];
        DateTime created_at = DateTime.Now;
        //Save all your required values, including user id and whatnot here.
        //The duration variable will allow you to see expensive page loads on the controller, this can be useful when clients complain about something being slow.
    }
}
Sign up to request clarification or add additional context in comments.

10 Comments

It looks pretty good. But for buttons and links clicked is going to work too?, The idea is that this statistic information is used by the designer to take decisions about what buttons or links are more used and which ones are not event clicked.
I'm afraid using this method you will not be able to work out which buttons/links are clicked. I don't know of any way of storing this data straight from the interface, but if all buttons/links call an action you could pass through a variable which is picked up in this method, this would unfortunately be time intensive adding to all your links. To do this pass "buttonClicked=name" and access it via the filterContext.HttpContext.Request.RawUrl variable. Not the best option though, and will only work for buttons which make a request to the server.
Probably can't get which buttons or links are clicked, but you could get referring URL, I think, through the ResultExecutedContext?
You can pass through the button name which was clicked if it's making a connection back to the server, but as mentioned above it'd be pretty horrible actually doing it. Much better idea using the referring URL to find out where the link was clicked as Kenny Eliasson said, I'm not sure off the top of my head about ResultExecutedContext but there'd be a way of doing it. Nice idea Kenny
Can you get the data that was posted from the action from this? For example, if I add that to an AddComment action, can I get the ID of the comment added, the text... ?
|
24

I just stumbled on these 2 posts by Rion Williams that describe a very straightforward way of doing this:

Implementing Audit Trails using ASP.NET MVC ActionFilters

Creating Advanced Audit Trails using ActionFilters in ASP.NET MVC

The advanced post is really great as you can store the request's data and further filter that data.

I'll implement this right now in my app.

2 Comments

Very useful and have now implemented in my app, thank you for the links.
@JonL did you custom implementation about it?
6

You could try using a PostSharp aspect to perform the logging for you, it's multi-cast functionality might come in handy for something like that. If it's not an option, then a Module would probably be the easiest to implement (assuming you can get the required user information at that point in the pipeline).

4 Comments

Can PostSharp target action methods unobtrusively? I'm thinking it would require attribute decoration, something I know my MVC actionmethods are a little heavy with. Once you get to 4-5 attributes I think things get ugly.
That was exactly my concern about using an http module, i don't know if i will be able to get the required data in that context.
A quick google search returned vyrotek.com/2008/using-postsharp-with-aspnet-mvc which seems promising. I haven't taken a look at the code yet, but it may be possible to use the two frameworks together after all.
@jfar PostSharp allows unobtrusive decoration using "multicasting". There is a small amount of work involved in narrowing down what aspects are applied to which methods but it does make for cleaner controllers: postsharp.net/blog/post/multicasting-of-custom-attributes
1

@Rory's idea is excelent. PostSharp is just what you need for this, you might consider coupling it with ASP.net Health Monitoring

4 Comments

I was looking at PostSharp it look interesting, i was just wondering if it requires a lot of configuration like log4net, or its pretty much straight forward like ELMAH.
Configuration, no. However it isn't just for logging so you kind of have to roll your own approach to it.
LAOS (the AOP framework that comes with PostSharp) is designed to work with all sorts of cross-cutting concerns, logging just happens to be one of them (and probably the most used example). The only thing that might be a problem is the interception code that is injected by the post-processor. As jfar commented on my answer, it might cause problems with the way the MVC framework does things, I honestly don't know if they would work together. I suggest you take a look at some of the examples and search around the net to see if someone else has successfully used them together.
I have used postsharp and MVC together without issue.

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.