Ajax action calls in Sitecore MVC

In our current project we are using Sitecore 7.2, with MVC.

First thing to note here, is the Url structure that is needed to be able to access controller actions from within a sitecore solution.

A sample Url would be:

http://local.mysite.com/api/sitecore/samplecontroller/sampleaction?sampleparam=abc

As you see above, the action can be accessed via sitecore’s api url, and this Url can be programmatically formed using the MVC helper method – Url.Action –

    Url.Action("sampleaction","samplecontroller")

Our site is very javascript / ajax heavy and at the beginning of this implementation, while making ajax calls to MVC actions, we came across the following issue:

net::ERR_CONNECTION_REFUSED n.ajaxTransport.k.cors.a.crossdomain.send

2015-02-27_014903

Even though we were making the ajax call from an http page – to another http url, we still faced this issue. The solution here was to ensure that all controller actions which would be invoked through ajax, have in the response header the ‘Access-Control-Allow-Origin *’ token.

Since we were using MVC – we decided to implement this using a custom MVC action filter and override the OnActionExecuting method.

using System.Web.Mvc;

namespace MySite._Classes.Shared.Customizations.MVC
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
            base.OnActionExecuting(filterContext);
        }
    }
}

Now all you’ve got to do after this, is add this new attribute above any method you intend to invoke via ajax! So following the example i mentioned above, here’s the action:

        [AllowCrossSiteJson]
        public JsonResult SignInJson(string email, string password, string redirectUrl = null,
            string pipeDelimitedMailingListIds = null, bool isRedirect = true)
        {
            ...
            ...
            return Json(<Serializable object>, JsonRequestBehavior.AllowGet);
        }

Also note the use of JsonRequestBehavior.AllowGet here – which would be absolutely mandatory in case you are trying to invoke this method via ajax using a GET request. In absence of this, you will get the following error:
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet
Also to note, an excerpt from the ASP.NET MVC Wrox publication book:

By default, the ASP.NET MVC framework does not allow you to respond to an HTTP GET request with a JSON payload. If you need to send JSON in response to a GET, you’ll need to explicitly allow the behavior by using JsonRequestBehavior.AllowGet as the second parameter to the Json method. However, there is a chance a malicious user can gain access to the JSON payload through a process known as JSON Hijacking. You do not want to return sensitive information using JSON in a GET request.

Now additionally – if you wanted to avoid adding the JsonRequestBehavior.AllowGet property on EVERY json returning action you write, you could choose the alternative route of overriding the OnResultExecuting() method in your custom action filter:

 public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var jsonResult = filterContext.Result as JsonResult;

        if (jsonResult == null)
            throw new ArgumentException("Action does not return a JsonResult, attribute AllowJsonGet is not allowed");

        jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        base.OnResultExecuting(filterContext);
    }

Nifty aint it?

One thought on “Ajax action calls in Sitecore MVC

Leave a comment