Detecting AJAX Requests in ASP.NET MVC6

In todays web applications, there is an overwhelming reliance on Javascript and it's used all of the time for handling all sorts of behaviors (i.e. building your entire framework, loading and manipulating DOM elements, etc.).

Often times, it can be useful to determine how specific requests come into your application and where they are originating from as you might want to limit what your user can and cannot access via plain GET and POST requests.

IsAjaxRequest() = false;

Previously, ASP.NET MVC applications could easily check if a request was being made via AJAX through the aptly named IsAjaxRequest() method that was an available method on the Request object as seen below :

public ActionResult YourActionName()
{
     // Check if the request is an AJAX call
     var isAjax = Request.IsAjaxRequest();

     // Do something about it.
}

An even more common use-case for this might be to build an ActionFilter that you could easily apply as an attribute to allow only AJAX-based requests to come through :

[AjaxOnly]
public ActionResult YourActionName()
{
     // Omitted for brevity
}

An older futures build of MVC3 had this attribute already built-in, however if you wanted to write it yourself, you could easily use something like :

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

However as one of the many sweeping changes that came across within the release of MVC6, you'll find that this method no longer exists.

[AjaxOnly] within MVC6

The IsAjaxRequest() actuallys works by simply performing a check for the X-Requested-With header as seen in the actual implementation of the function from MVC5 :

public static bool IsAjaxRequest(this HttpRequestBase request)
{
  if (request == null)
    throw new ArgumentNullException("request");
  if (request["X-Requested-With"] == "XMLHttpRequest")
    return true;
  if (request.Headers != null)
    return request.Headers["X-Requested-With"] == "XMLHttpRequest";
  return false;
}

Now since several of the context-related parameters have changed in MVC 6, the implementation of an [AjaxOnly] attribute would have to change slightly as well by modeling it after its predecessor :

public class AjaxOnlyAttribute : ActionMethodSelectorAttribute
{
       public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
        {
            return routeContext.HttpContext.Request?.Headers["X-Requested-With"] == "XMLHttpRequest";
        }
}

And basically that's it, you can just throw the [AjaxOnly] attribute on any of your existing requests and it will allow / deny them based on if the originated via AJAX or not.