Search code examples
c#asp.netasp.net-mvcasp.net-web-apiaction-filter

.Net Filter For Wrapping JsonResult Actions Response


I've built a Web API application and found an issue (which currently treated badly in my code), the issue summarized in wrapping all Json objects which returned from All API actions with custom nodes(roots).

i.e: I have this json (array) response:

[
  {
    "Category": "Pages",
    "Users": [
      {
        "ID": "1",
        "Fname": "Foo",
        "Lname": "Bar"
      }
    ]
  }
]

And Need this response:

{
  "Object": {
    "Body": [
      {
        "Category": "Pages",
        "Users": [
          {
            "ID": "1",
            "Fname": "Foo",
            "Lname": "Bar"
          }
        ]
      }
    ]
  }
}

So here I just wrapped the response inside {"Object":{"Body": <Response Here>}}

And this I need it to be applied on all API Json responses of type Array.

And for simple Json object response, I need it just to be wrapped like {"Object": <Response Here>}

I wrapped the Json response currently in each controller action by this code:

 public JsonResult Categories()
 {
   return Json(new { Object= new { Body= GetCategoriesList() } }, JsonRequestBehavior.AllowGet);
 }

Sure this achievement is so bad because I have to repeat this wrapping in each action.

My Question Is:

How to create ActionFilterAttribute to be called after each action execution to wrap the response as per the above Json sample?

i.e. for creating the filter:

 public class JsonWrapper: System.Web.Mvc.ActionFilterAttribute
 {
   public override void OnActionExecuted(ActionExecutedContext filterContext)
   {
   }
 }

i.e. for calling the filter:

[JsonWrapper]
public class APIController : Controller

And also to set the response content type in the same filter "application/json"


Solution

  • If suppose here if what you looking for:

    public class JsonWrapperAttribute : ActionFilterAttribute, IActionFilter
    {
        void IActionFilter.OnActionExecuted(ActionExecutedContext context)
        {
            //Check it's JsonResult that we're dealing with
            JsonResult jsonRes = context.Result as JsonResult;
            if (jsonRes == null)
                return;
    
            jsonRes.Data = new { Object = new { Body = jsonRes.Data } }
        }
    }
    

    Here is how you can use it:

    [JsonWrapper]
    public JsonResult Index()
    {
        var data = new
        {
            a = 1,
            b = 2
        };
        return Json(data, JsonRequestBehavior.AllowGet);
    }
    

    Result will be:

    {"Object":{"Body":{"a":1,"b":2}}}