用于包装 JsonResult 操作响应的 .Net 过滤器

.Net Filter For Wrapping JsonResult Actions Response

我构建了一个 Web API 应用程序 并发现了一个问题(目前在我的代码中处理不当),该问题总结在包装所有 Json 从具有自定义节点(根)的所有 API 操作返回的对象。

即:我有这个 json(数组)响应:

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

并且需要这个回复:

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

所以这里我只是将响应包装在 {"Object":{"Body": <Response Here>}}

我需要将其应用到 Array.

类型的所有 API Json 响应中

对于简单的 Json 对象响应,我需要它像 {"Object": <Response Here>}

一样包装

我通过以下代码包装了当前每个控制器操作中的 Json 响应:

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

当然这个成就很糟糕,因为我必须在每个动作中重复这个包装。

我的问题是:

如何创建 ActionFilterAttribute 在每个操作执行后调用以根据上述 Json 示例包装响应?

即用于创建过滤器:

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

即用于调用过滤器:

[JsonWrapper]
public class APIController : Controller

并在同一个过滤器中设置响应内容类型"application/json"

假设这里是你要找的东西:

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 } }
    }
}

以下是使用方法:

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

结果将是:

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

为了避免在每个操作中重复换行,您可以编写一个扩展方法来为您换行

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
        };
    }
}

或创建一个新的 ActionResult class(并向 return 添加扩展方法)

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}}; }
    }
}