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!

image 

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();
            logMessage.AppendLine(context.ActionMethod.Name);
            
            if(context.Result.GetType() == typeof(RenderViewResult))
            {
                RenderViewResult viewResult = context.Result as RenderViewResult;
                logMessage.AppendLine("ActionResult: RenderViewResult");
                logMessage.AppendLine();
                logMessage.AppendLine(Dumper.DumpObject(viewResult.ViewData, 5));
            }
            logMessage.AppendLine();
            log.Info(logMessage.ToString());
        }

    }
}

And now just add the attribute above the Controller:

[Log]
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=1.0.0.0, 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=1.0.0.0, 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=1.0.0.0, 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=1.0.0.0, Culture=neutral, PublicKeyToken=null]] = System.Data.Linq.EntityRef`1[Mvc2.Models.DataObjects.Category]
|||+PropertyChanging AS System.ComponentModel.PropertyChangingEventHandler = System.ComponentModel.PropertyChangingEventHandler
|||+(System.MulticastDelegate)
|||+(System.Delegate)
||+[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.

Recent Posts

  • HowTo: make out Retweet-counter in a random URL

      Twitter offers some interesting functions with the integration of the twitter button – every user can see how often the website has been retweeted and he can do the same with just one click. But of course the whole thing has his price: - The integration of the Twitter JavaScript makes the whole data […]

  • Time-controlled Azure WebJobs – Azure as easy as it get‘s

        While still in development the Azure WebJob SDK offers some cool features for procession and supply of information. A good example is the sample that observes the Azure Queue and processes an item as soon as it spots one.   Scenario: time-controlled activities – without queue and so on My scenario was quite […]

  • image2021-570x194_thumb.png
    HowTo: Create RSS Feeds with ASP.NET MVC

    I’ve already written about how to consume RSS or Atom Feeds with the SyndicationFeed (in German, sry) but todays post is about how to create or publish an own feed. Beside the age of the feed standard and the much defamation from Facebook, Twitter and Google on RSS/Atom I consider this easy to consume API […]

  • image1997-311x194_thumb.png
    How to access an Azure Website with the local IIS Manager

    Since the end of February it is possible to access an Azure Website with the IIS Manager. Although the Azure Management site offers some information there are more details visible at the IIS Manager. For the connection you will need an IIS Manager and the IIS Manager for Remote Administration Extension. It’s also possible to […]

  • 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 […]

Support us