ASP.NET MVC: Using a ActionFilter for logging

The "pre-" preview 3 of the MVC Framework (see here for more information) introduced new features for the ActionFilter.

The "FilterExecutingContext" (using in the OnActionExecuted method) and "FilterExecutedContext" (using in the OnActionExecuting method) are now called "ActionEx…Context".

This is the complete method list from an ActionFilter in this pre-preview:

        public override void OnActionExecuting(ActionExecutingContext filterContext)
            ActionExecutingContext contect = filterContext;
            string test = contect.ActionMethod.ToString();

        public override void OnActionExecuted(ActionExecutedContext filterContext)
            ActionExecutedContext context = filterContext;
            string test = context.ActionMethod.ToString();

        public override void OnResultExecuting(ResultExecutingContext filterContext)
            ResultExecutingContext context = filterContext;
            string test = context.ToString();

        public override void OnResultExecuted(ResultExecutedContext filterContext)
            ResultExecutedContext context = filterContext;
            string test = context.ToString();

A great new feature: You have access to the viewdata form the…

  • ResultExecutedContext
  • ResultExecutingContext
  • ActionExecutedContext Yeah!


With this feature we can now build a very smart logger: Get all ViewData typ information recursive and save this by using Log4Net.

I use this "DumpObject Code" and configure Log4Net like this guy.

The "simple log FilterAction":

namespace Mvc2.Filters
    public class LogAttribute : ActionFilterAttribute
        private static readonly ILog log = LogManager.GetLogger(typeof(LogAttribute).Name);

        public override void OnActionExecuted(ActionExecutedContext filterContext)
            ActionExecutedContext context = filterContext;
            StringBuilder logMessage = new StringBuilder();
            if(context.Result.GetType() == typeof(RenderViewResult))
                RenderViewResult viewResult = context.Result as RenderViewResult;
                logMessage.AppendLine("ActionResult: RenderViewResult");
                logMessage.AppendLine(Dumper.DumpObject(viewResult.ViewData, 5));


And now just add the attribute above the Controller:

public class EntryController : Controller

The result in the log.txt:

2008-04-17 20:41:02,204 [10] INFO  LogAttribute [(null)] - List
ActionResult: RenderViewResult

[ObjectToDump] AS Mvc2.Views.Entry.ListViewData = Mvc2.Views.Entry.ListViewData
+<EntryList>k__BackingField AS Mvc2.Helpers.PagedList`1[[Mvc2.Models.DataObjects.Entry, Mvc2, Version=, Culture=neutral, PublicKeyToken=null]] = Mvc2.Helpers.PagedList`1[Mvc2.Models.DataObjects.Entry]
|+<TotalPages>k__BackingField AS System.Int32 = 2
|+<TotalCount>k__BackingField AS System.Int32 = 17
|+<PageIndex>k__BackingField AS System.Int32 = 1
|+<PageSize>k__BackingField AS System.Int32 = 10
+(System.Collections.Generic.List`1[[Mvc2.Models.DataObjects.Entry, Mvc2, Version=, Culture=neutral, PublicKeyToken=null]])
|+_items AS Mvc2.Models.DataObjects.Entry[] = Mvc2.Models.DataObjects.Entry[]
||+[0] AS Mvc2.Models.DataObjects.Entry = Mvc2.Models.DataObjects.Entry
|||+_Id AS System.Guid = 797c70f0-f571-4969-80e8-d4a085445b6d
|||+_Title AS System.String = test
|||+_Url AS System.String = test
|||+_UserId AS System.Guid = cf2e5ccc-bd32-405d-bd54-eda112ebe06c
|||+_Link AS System.String = http...
|||+_Description AS System.String = tealkjdlsakj
|||+_CategoryId AS System.Guid = 7bd8028e-02c1-45f4-a0a6-403f5bf0ff0c
|||+_Date AS System.DateTime = 17.04.2008 15:48:53
|||+_EntryTags AS System.Data.Linq.EntitySet`1[[Mvc2.Models.DataObjects.EntryTag, Mvc2, Version=, Culture=neutral, PublicKeyToken=null]] = System.Data.Linq.EntitySet`1[Mvc2.Models.DataObjects.EntryTag]
|||+_Category AS System.Data.Linq.EntityRef`1[[Mvc2.Models.DataObjects.Category, Mvc2, Version=, Culture=neutral, PublicKeyToken=null]] = System.Data.Linq.EntityRef`1[Mvc2.Models.DataObjects.Category]
|||+PropertyChanging AS System.ComponentModel.PropertyChangingEventHandler = System.ComponentModel.PropertyChangingEventHandler
||+[1] AS Mvc2.Models.DataObjects.Entry = Mvc2.Models.DataObjects.Entry
|||+_Id AS System.Guid = 8e1554c1-47fa-4db5-af41-91c3fcf92fb3
|||+_Title AS System.String = EntryTitle
|||+_Url AS System.String = EntryTitle_13
|||+_UserId AS System.Guid = cf2e5ccc-bd32-405d-bd54-eda112ebe06c
|||+_Link AS System.String = http://.../
|||+_Description AS System.String = Blabla
|||+_CategoryId AS System.Guid = 16d09b0a-2157-43b7-a881-b536e90f7fbf

This is not the perfect solution – but it should show the "power" of the new ActionFilters.

I will try to create a better (and more readable) version in the next days – with the RouteData/submitted parameters and so on :)

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.

About the author

Written by

Currently there is no additional info about this author.

3 Responses

Comment on this post

Recent Posts

  • image1929-570x143_thumb.png
    Create and validate own Json-Web-Tokens (JWTs)

    If you are interested in web authentication you probably have heard about JSON Web tokens (JWT). What is a JWT? Maybe I’m not using the correct security termination but however: JWTs are used to exchange claims between two systems. For example: You want to log on to a service (like Facebook, Twitter, etc.) and want […]

  • Micro-Optimization: how to shrink or „embed“ pictures

      I’m currently working on the “CodeInside Dashboard” and since the page structure isn’t that difficult it should be possible to fulfill all of Google Pagespeed or Yahoos YSlow recommendations. One of the rules was to optimize the 4 PNGs that are embedded on the page.   Before – without optimization: Below you can see […]

  • image1979-570x194.png
    Move to Windows Azure – VMs, Word Press Migration, DNS changes

    Since mid January this blogs runs on a WordPress installation in an Azure VM. Because I always thought that the subject is quite complicated this blogpost offers a view behind the scenes. Why this move? So far this blog (both German and English Version) runs on a hoster somewhere in Germany. The main problem with this […]

  • Windows Azure Active Directory – CRUD for users and groups

      Windows Azure Active Directory? If you are not informed about the subject I recommend you to have a look on this Azure Info site. Which resources are there? The Azure AD contains the following entities: - Users - Groups - Contacts - Roles Access to the directory or on the “directory graph” Although the […]

  • Introduction into SignalR 2.0 & Azure Website Websockets

      SignalR is an Open Source Framework for Real Time WebApps. The main problem with Real-Time in the web is the canal between Browser and Server. If you never had to deal with SignalR and this problem before here is a brief introduction:   The problem Traditionally the browser initiates the request to the server […]

Support us