DNN Development Tips:10 - Using Action Filters in your Services Framework methods
In an earlier blog I described the use of the DnnExceptionFilterAttribute which can be used to simplify the exception handling in Services Framework action methods. In this blog I turn my attention to another, more generic attribute that you can apply to your action methods.
As with the ExceptionFilterAttribute, ASP.NET Web API provides a base class that you can extend to create your own custom Action Filter. The ActionFilterAttribute provides two methods:
OnActionExecuting – this is called just before your action method is invoked.
OnActionExecuted – this is called just after your action method completes
There are many cases where you might have some common code that you want to execute before and after many if not all of your action methods. One example is when using the DAL 2 data access pattern.
Figure 1 shows the same method we used in the previous blog.
Listing 1: The DeleteTask Action Method |
1: [HttpPost] 2: [DnnExceptionFilter(MessageKey = "DeleteTask.Error")] 3: public HttpResponseMessage DeleteTask(TaskDTO taskDTO) 4: { 5: using (var context = DataContext.Instance()) 6: { 7: var repo = context.GetRepository 8: var task = repo.GetById(taskDTO.TaskId, ActiveModule.ModuleID); 9: 10: repo.Delete(task); 11: var result = new {Result = "success"}; 12: return Request.CreateResponse(HttpStatusCode.OK, result); 13: } 14: } |
Now while the using code is fairly simple you do have to remember to use this approach. Lets modify this to use a TaskActionFilter. This is shown in Listing 2.
Listing 2: The TaskActionFilterAttribute class |
1: public class TaskActionFilterAttribute : ActionFilterAttribute 2: { 3: private IDataContext _dataContext; 4: 5: public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 6: { 7: _dataContext.Dispose(); 8: 9: base.OnActionExecuted(actionExecutedContext); 10: } 11: 12: public override void OnActionExecuting(HttpActionContext actionContext) 13: { 14: 15: dynamic controller = actionContext.ControllerContext.Controller; 16: _dataContext = DataContext.Instance(); 17: controller.DataContext = _dataContext; 18: base.OnActionExecuting(actionContext); attri 19: } 20: } |
In the OnActionExecuting method, we get an “instance” of the DataContext and set it to the DataContext property of the Controller. Note that we need the Controller to be a dynamic object for this to work, and when the attribute is used we will need to provide a property called DataContext.
And – as we are replacing the using statement we will need to dispose of the DataContext instance in the OnActionExecuted method
Lets look at what the Web API method will look like now (see Listing 3)
Listing 3: The DeleteTask method after applying the TaskActionFilter attribute |
1: [HttpPost] 2: [TaskActionFilter] 3: [DnnExceptionFilter(MessageKey = "DeleteTask.Error")] 4: public HttpResponseMessage DeleteTask(TaskDTO taskDTO) 5: { 6: var repo = DataContext.GetRepository 7: var task = repo.GetById(taskDTO.TaskId, ActiveModule.ModuleID); 8: 9: repo.Delete(task); 10: var result = new {Result = "success"}; 11: return Request.CreateResponse(HttpStatusCode.OK, result); 12: } |
This was a rather simple example to demonstrate the point, but the use of Action Filter’s can make your Web API Action methods much easier to read and understand.