.Net Filter For Wrapping JsonResult Actions Respon

2019-07-16 18:46发布

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"

2条回答
对你真心纯属浪费
2楼-- · 2019-07-16 19:14

To prevent yourself having to repeat wrapping in each action you could either write an extension method which would do the wrapping for you

public static class ControllerExtensions 
{
    public static JsonResult WrappedJson(this Controller controller, object data, JsonRequestBehavior behavior)
    {
        return new JsonResult
        {
            Data = new { Object = new { Body = data } },
            JsonRequestBehavior = behavior
        };
    }
}

or create a new ActionResult class (and add extension methods to return that)

public class WrappedJsonResult : JsonResult
{
    public new object Data
    {
        get
        {
            if (base.Data == null)
            {
                return null;
            }

            return (object) ((dynamic) base.Data).Object.Body;
        }

        set { base.Data = new {Object = new {Body = value}}; }
    }
}
查看更多
虎瘦雄心在
3楼-- · 2019-07-16 19:39

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}}}
查看更多
登录 后发表回答