ASP.NET MVC 4 Custom Action Filters #1

Exercise 1: Logging Actions

In this exercise, you will learn how to create a custom action log filter by using ASP.NET MVC 4 Filter Providers. For that purpose you will apply a logging filter to the MusicStore site that will record all the activities in the selected controllers.

The filter will extend ActionFilterAttributeClass and override OnActionExecuting method to catch each request and then perform the logging actions. The context information about HTTP requests, executing methods, results and parameters will be provided by ASP.NET MVC ActionExecutingContext class.

Note: ASP.NET MVC 4 also has default filters providers you can use without creating a custom filter. ASP.NET MVC 4 provides the following types of filters:

  • Authorization filter, which makes security decisions about whether to execute an action method, such as performing authentication or validating properties of the request.
  • Action filter, which wraps the action method execution. This filter can perform additional processing, such as providing extra data to the action method, inspecting the return value, or canceling execution of the action method
  • Result filter, which wraps execution of the ActionResult object. This filter can perform additional processing of the result, such as modifying the HTTP response.
  • Exception filter, which executes if there is an unhandled exception thrown somewhere in action method, starting with the authorization filters and ending with the execution of the result. Exception filters can be used for tasks such as logging or displaying an error page.

For more information about Filters Providers please visit this MSDN link: (http://msdn.microsoft.com/en-us/library/dd410209.aspx) .

About MVC Music Store logging feature

This Music Store solution has a new data model table for site logging, ActionLog, with the following fields: Name of the controller that received a request, Called action, Client IP and Time stamp.

Data-model.-ActionLog-table

Data model – ActionLog table

The solution provides an ASP.NET MVC View for the Action log that can be found at MvcMusicStores/Views/ActionLog:

Action-Log-view

Action Log view

With this given structure, all the work will be focused on interrupting controller’s request and performing the logging by using custom filtering.

Task 1 – Creating a Custom Filter

In this task you will create a custom filter attribute class to catch a controller’s Request that will contain the logging logic. For that purpose you will extend ASP.NET MVC ActionFilterAttribute Class and implement the interface IActionFilter.

Note: The ActionFilterAttribute is the base class for all the attribute filters. It provides the following methods to execute a specific logic after and before controller action’s execution:

  • OnActionExecuting(ActionExecutedContext filterContext): Just before the action method is called.
  • OnActionExecuted(ActionExecutingContext filterContext): After the action method is called and before the result is executed (before view render).
  • OnResultExecuting(ResultExecutingContext filterContext): Just before the result is executed (before view render).
  • OnResultExecuted(ResultExecutedContext filterContext): After the result is executed (after the view is rendered).

By overriding any of these methods into a derived class, you can execute your own filtering code.

  1. Open the Begin solution located at \Source\Ex01-LoggingActions\Begin folder.
    1. You will need to download some missing NuGet packages before continue. To do this, click the Projectmenu and select Manage NuGet Packages.
    2. In the Manage NuGet Packages dialog, click Restore in order to download missing packages.
    3. Finally, build the solution by clicking Build | Build Solution.

    Note: One of the advantages of using NuGet is that you don’t have to ship all the libraries in your project, reducing the project size. With NuGet Power Tools, by specifying the package versions in the Packages.config file, you will be able to download all the required libraries the first time you run the project. This is why you will have to run these steps after you open an existing solution from this lab.

    For more information, see this article: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages.

  2. Add a new C# class into the Filters folder and name it CustomActionFilter.cs. This folder will store all the custom filters.
  3. Open CustomActionFilter.cs and add a reference to System.Web.Mvc and MvcMusicStore.Modelsnamespaces:(Code Snippet – ASP.NET MVC 4 Custom Action Filters – Ex1-CustomActionFilterNamespaces)C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MvcMusicStore.Models;
    
  4. Inherit the CustomActionFilter class from ActionFilterAttribute and then make CustomActionFilterclass implement IActionFilter interface.C#
    ...
    namespace MvcMusicStore.Filters
    {
        public class CustomActionFilter : ActionFilterAttribute, IActionFilter
        {
            ...
  5. Make CustomActionFilter class override the method OnActionExecuting and add the necessary logic to log the filter’s execution. To do this, add the following highlighted code within CustomActionFilter class.(Code Snippet – ASP.NET MVC 4 Custom Action Filters – Ex1-LoggingActions)C#
    public class 
    
    CustomActionFilter : ActionFilterAttribute, IActionFilter
    {
        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            // TODO: Add your acction filter's tasks here
    
            // Log Action Filter Call
            MusicStoreEntities storeDB = new MusicStoreEntities();
    
            ActionLog log = new ActionLog()
            {
                Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
                Action = filterContext.ActionDescriptor.ActionName + " (Logged By: Custom 
    Action Filter)",
                IP = filterContext.HttpContext.Request.UserHostAddress,
                DateTime = filterContext.HttpContext.Timestamp
            };
    
            storeDB.ActionLogs.Add(log);
            storeDB.SaveChanges();
    
            this.OnActionExecuting(filterContext);
        }
    }

    Note: OnActionExecuting method is using Entity Framework to add a new ActionLog register. It creates and fills a new entity instance with the context information from filterContext.

    You can read more about ControllerContext class at msdn.

Task 2 – Injecting a Code Interceptor

In this task you will add the custom filter by injecting it to all controller classes and controller actions that will be logged. For the purpose of this exercise, the Store Controller class will have a log.

The method OnActionExecuting from ActionLogFilterAttribute custom filter runs when an injected element is called.

It is also possible to intercept a specific controller method.

  1. Open the StoreController at MvcMusicStore\Controllers and add a reference to the Filters namespace:C#
    using System.Linq;
    using System.Web.Mvc;
    using MvcMusicStore.Models;
    using MvcMusicStore.Filters;
    
  2. Inject the custom filter CustomActionFilter into StoreController class by adding [CustomActionFilter]attribute before the class declaration.C#
    ...
    [CustomActionFilter]
    public class StoreController : Controller
    {
        ...
    }

    Note: When a filter is injected into a controller class, all its actions are also injected. If you would like to apply the filter only for a set of actions, you would have to inject [CustomActionFilter] to each one of them:

    C#

    [CustomActionFilter]
    public ActionResult Index()
    {
      ...
    }
    
    [CustomActionFilter]
    public ActionResult Browse(string genre)
    {
      ...
    }

Task 3 – Running the Application

In this task, you will test that the logging filter is working. You will start the application and visit the store, and then you will check logged activities.

  1. Press F5 to run the application.
  2. Browse to /ActionLog to see log view initial state:

Log-tracker-status-before-page-activity

Log tracker status before page activity

Note: By default, it will always show one item that is generated when retrieving the existing genres for the menu.

For simplicity purposes we’re cleaning up the ActionLog table each time the application runs so it will only show the logs of each particular task’s verification.

You might need to remove the following code from the Session_Start method (in the Global.asax class), in order to save an historical log for all the actions executed within the Store Controller.

C#

// Clean up Logs Table
MusicStoreEntities storeDB = new MusicStoreEntities();
foreach (var log in 

storeDB.ActionLogs.ToList())
{
   storeDB.ActionLogs.Remove(log);
}

storeDB.SaveChanges();
  1. Click one of the Genres from the menu and perform some actions there, like browsing an available album.
  2. Browse to /ActionLog and if the log is empty press F5 to refresh the page. Check that your visits were tracked:

Action-log-with-activity-logged

Action log with activity logged

Yosef Sukianto has written 36 articles

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>