Restrict ASP.NET MVC Action's Using The ActionMethodSelectorAttribute

Posted by: Malcolm Sheridan , on 8/3/2010, in Category ASP.NET MVC
Views: 35383
Abstract: The following article demonstrates how to restrict ASP.NET MVC action methods before they're executed via the ActionMethodSelectorAttribute class.
A huge reason why I love ASP.NET MVC is its flexibility and it is extensible. I recently came across a topic on the forums on how to restrict certain HTTP requests when using ASP.NET MVC. This is a perfect scenario to create your own custom action filter attribute! This is easy! All you need to do is create a class that inherits ActionMethodSelectorAttribute. This is different from inheriting from the ActionFilterAttribute class as that's the base class for all action filter attributes. If I was going to do logging or checking incoming HTTP parameters, this class would be the one to use, but I want a lightweight class that will check the incoming HTTP request and either allow the request access to the code, or restrict it. This is why I chose to use the ActionMethodSelectorAttribute class as no action will be executed until the request has passed the validation. You can certainly use ActionFilterAttribute, but that means you're not restricting the requests, but checking the events when the action is executed.
 
To see this in action, I'm going to create a small ASP.NET MVC 2 website. If you haven't got Microsoft Visual Studio 2010, you can download the Express edition here
I want to create two scenarios. The first scenario is restricting action methods to Ajax requests. To find out if the HTTP request is an Ajax request, we can use the following code:
 
This is part of the System.Web.Mvc.AjaxRequestExtensions class and checks the incoming HTTP request for the X-Requested-With key in the request or the request headers. This value is mainly used to identify Ajax requests.
 
To restrict action methods from only being called from Ajax requests, I’m going to create a class called HttpAjaxRequestAttribute and add the following code:
 
C#
 
public class HttpAjaxRequestAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        if (!controllerContext.HttpContext.Request.IsAjaxRequest())
        {
            throw new Exception("This action " + methodInfo.Name + " can only be called via an Ajax request");
        }
        return true;
    }
}
 
 
VB.NET (Converted)
 
Public Class HttpAjaxRequestAttribute
      Inherits ActionMethodSelectorAttribute
      Public Overrides Function IsValidForRequest(ByVal controllerContext_Renamed As ControllerContext, ByVal methodInfo As System.Reflection.MethodInfo) As Boolean
            If Not controllerContext_Renamed.HttpContext.Request.IsAjaxRequest() Then
                  Throw New Exception("This action " & methodInfo.Name & " can only be called via an Ajax request")
            End If
            Return True
      End Function
End Class
 
 
In the code above, I’ve created a class that inherits the ActionMethodSelectorAttribute class. This allows me to restrict the HTTP requests coming into an action before it is executed. I’m overriding one method, IsValidForRequest, which simply returns a boolean value which indicates success or failure. If the incoming request isn’t via an Ajax call, I’m throwing an error:
C#
if (!controllerContext.HttpContext.Request.IsAjaxRequest())
{
throw new Exception("This action " + methodInfo.Name + " can only be called via an Ajax request");
}
 
Because ActionMethodSelectorAttribute inherits System.Attribute, I can now use this to decorate any action in a controller like this:
[HttpAjaxRequest]
[HttpGet]
public ActionResult AjaxActionOnly()
{
return Json(string.Empty);
}
 
VB.NET (Converted)
If Not controllerContext.HttpContext.Request.IsAjaxRequest() Then
Throw New Exception("This action " & methodInfo.Name & " can only be called via an Ajax request")
End If
 
 
Likewise I can create an attribute that will restrict calls to an action method unless they’re being called from a secure connection. Here’s the code below:
C#
public class HttpsAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
       {
       if (!controllerContext.HttpContext.Request.IsSecureConnection)
            {
                throw new SecurityException("This action " + methodInfo.Name + " can only be called via SSL");
            }
            return true;
        }
}
 
VB.NET (Converted)
 
Public Class HttpsAttribute
      Inherits ActionMethodSelectorAttribute
Public Overrides Function IsValidForRequest(ByVal controllerContext_Renamed As ControllerContext, ByVal methodInfo As System.Reflection.MethodInfo) As Boolean
         If Not controllerContext_Renamed.HttpContext.Request.IsSecureConnection Then
                        Throw New SecurityException("This action " & methodInfo.Name & " can only be called via SSL")
         End If
                  Return True
End Function
End Class
 
 
The following line of code checks is the incoming request is secure:
HttpContext.Request.IsSecureConnection()
Again I can decorate any action method now to ensure they’re secure:
C#
[Https]
public ActionResult SslActionOnly()
{
return View();
}
 
VB.NET (Converted)
 
<Https>
Public Function SslActionOnly() As ActionResult
Return View()
End Function
 
This is another reason why I like working with ASP.NET MVC. The entire source code of this article can be downloaded over here
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @malcolmsheridan


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Tony Woll on Thursday, August 5, 2010 1:08 PM
excellent mvc tip!
Comment posted by www.custodiestensi.it on Thursday, June 13, 2013 1:27 PM
Yes excellent. I confirm.

www.custodiestensi.it

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel