Search code examples
asp.net-mvcaction-filter

Intercept JsonResult and wrap it (as string)


I have a action that return JsonResult.
I want to intercept the JsonResult return and wrap it with string.

Something like:

 public class JsonProxyAttribute : FilterAttribute
    {
        void OnActionExecuting(ExceptionContext filterContext)
        {
            var res = filterContext.Result as string;
            if (res != null)
            {
                filterContext.Result = "func("+filterContext.Result+")";
            }
        }
    }

So the ajax call will get this:

func({"MyContent":"content"})

instead of this:

{"MyContent":"content"}

Solution

  • What you need is to create a new ActionResult that will extend JsonResult and represent JSONP

    public class JsonpResult : JsonResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = ContentType ?? "application/x-javascript";
            response.ContentEncoding = ContentEncoding ?? System.Text.Encoding.UTF8;
    
            if (Data != null)
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                string ser = serializer.Serialize(Data);
                response.Write("func(" + ser + ");");
            }
        }
    }
    

    Now if you want to intercept regular JSON results, your ActionFilter would look like this.

    public class JsonProxyAttribute : FilterAttribute
    {
        void OnActionExecuting(ExceptionContext filterContext)
        {
            var res = filterContext.Result as JsonResult;
            if (res != null)
            {
                filterContext.Result = new JsonpResult
                {
                    ContentEncoding = res.ContentEncoding,
                    ContentType = res.ContentType,
                    Data = res.Data,
                    JsonRequestBehavior = res.JsonRequestBehavior
                };
            }
        }
    }
    

    Or you can use JSONP directly in your controllers

    public ActionResult Jsonp()
    {
        var model = new List<string> { "one", "two" };
        return new JsonpResult
        {
            Data = model,
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }