ASP.NET MVC Action Filter – Ajax Only Attribute

The website I’m currently working on has a lot of AJAX incorporated in it, so my controller has a few actions which are only called in AJAX. At first I was using HttpContext.Request.IsAjaxRequest() within my action to control if the request was indeed an Ajax one, but I didn’t like the fact that I needed to call HttpContext in my control; it also made a lot of redundant code. That is why I decided to build an Action Filter that would do that for me.

Here’s the Action Filter

    public class AjaxOnlyAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if(!filterContext.HttpContext.Request.IsAjaxRequest())
                filterContext.HttpContext.Response.Redirect("/error/404");
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {

        }
    }

And an implementation example

    [AjaxOnly]
    public ActionResult AjaxActionMethod()
    {
        ....
    }

This might not be the best solution, but works pretty good for me so far!

This entry was posted on Wednesday, May 27th, 2009 at 3:03 pm and is filed under ASP.NET, C#.NET, Developement, MVC. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

9 Responses to “ASP.NET MVC Action Filter – Ajax Only Attribute”

Andrew Nurse May 28th, 2009 at 12:00 pm

Cool stuff. Maybe you could convert it from an Action Filter to an Action Selector though, similar to the AcceptVerbs attribute. Then, a non ajax result to that method will act like a request to a non-existant action.

(See System.Web.Mvc.ActionMethodSelectorAttribute)

Andrew Gunn May 28th, 2009 at 12:25 pm

Good article. Instead of hard-coding the 404 redirect, I’d change the response’s status code and let ASP.NET decide where the user should go:

filterContext.HttpContext.Response.StatusCode = 401;

Alternatively, you could wrap this up in a class that inherits from ActionResult (just like AuthorizeAttribute):

public class HttpNotFoundResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException(“context”);
}
context.HttpContext.Response.StatusCode = 401;
}
}

…and set the result of the filter context:

filterContext.Result = HttpNotFoundResult;

Hope this helps.

Andrew Gunn May 28th, 2009 at 12:25 pm

I mean:

filterContext.Result = new HttpNotFoundResult();

Andrew Gunn May 28th, 2009 at 12:26 pm

And obviously, the 401 should be 404. Third time lucky!

dervalp May 28th, 2009 at 8:42 pm

I am wondering, is that a normal behavior to put your action “Ajax only” ? For me yes, cause sometime you want to use function only with ajax and if you’re trying the put the url in the browser, sending a 404 is a normal behavior. But if it’s a normal way, why this function is not integrate in the MVC framework ? Is there someone who knows more about this ?

Mike May 28th, 2009 at 10:20 pm

I’m pretty sure we will see such an attribute in a future MVC release, don’t forget we’re still at version 1.0!

andrexx May 29th, 2009 at 1:54 am

Such attribute already exist in MvcFutures assembly – AcceptAjaxAttribute,
but throw Exception instead 404 error.

Martin Karlsson February 2nd, 2010 at 9:12 am

Big warning sign: Some hardware firewalls (e.g. Watchguard) have a feature that silently removes all “non-standard” HTTP headers, including the X-Requested-With header which IsAjaxRequest() checks. So if your AJAX requests suddenly start getting 404′s you now know why!

Lee smith March 3rd, 2011 at 5:57 am

Same thing but updated for MVC 3:

[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute: ActionFilterAttribute
{

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new HttpNotFoundResult();
}

base.OnActionExecuting(filterContext);
}
}

Leave a Reply