【问题标题】:.Net Filter For Wrapping JsonResult Actions Response.Net 过滤器用于包装 JsonResult 操作响应
【发布时间】:2016-08-24 10:29:38
【问题描述】:

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

即:我有这个 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"

【问题讨论】:

标签: c# asp.net asp.net-mvc asp.net-web-api action-filter


【解决方案1】:

如果在这里假设您正在寻找什么:

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

【讨论】:

  • 感谢完美
  • 如果我需要为 Json 对象(不是 Json 对象数组)创建不同的包装,例如 {"Body":{"a":1,"b":2} 并保持数组一样
  • @MoamenNaanou 将行 Data = new { Object = new { Body = jsonRes.Data } } 更改为您喜欢的任何结构。
  • @MoamenNaanou 它是 JsonArray 因为我们在这里检查了 JsonResult:JsonResult jsonRes = context.Result as JsonResult; if (jsonRes == null) return
  • 我认为属性的使用会很混乱。不查看代码,如果应用属性但返回 ViewResult 等会发生什么?如果你坚持使用该属性,则无需创建新的 JsonResult 并将其分配给上下文,只需执行 jsonRes.Data = new { Object = new { Body = jsonRes.Data } }
【解决方案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 类(并添加扩展方法以返回它)

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

【讨论】:

    猜你喜欢
    • 2014-04-17
    • 2012-03-23
    • 1970-01-01
    • 2018-08-02
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    相关资源
    最近更新 更多