Moamen Naanou Moamen Naanou - 3 months ago 15
ASP.NET (C#) Question

.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"

Answer

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;

        //copy all properties and modify Data
        context.Result = new JsonResult
        {
            ContentEncoding = jsonRes.ContentEncoding,
            ContentType = jsonRes.ContentType,
            JsonRequestBehavior = jsonRes.JsonRequestBehavior,
            MaxJsonLength = jsonRes.MaxJsonLength,
            RecursionLimit = jsonRes.RecursionLimit,
            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}}}