2016-08-24 34 views
2

我已经建立了一个的Web API应用程序,发现了一个问题(目前在我的代码处理不好),在包装从所有API操作返回所有Json对象概括的问题自定义节点(根)。净过滤器用于包装JsonResult举动的反应

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

+1

[在MVC 4正确的JSON序列]的可能的复制(http://stackoverflow.com/questions/17244774/proper-json-serialization-in-mvc-4) – MrClan

+0

你需要一个**定制JSON序列化器**而不是过滤器。 – MrClan

回答

3

如果这里假设如果你要找的东西:

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

感谢它的完美 –

+0

如果我需要为Json对象(不是Json对象数组)创建不同的包装,就像{“Body”:{“a”:1,“b”:2}并保持数组相同 –

+0

@ MoamenNaanou将'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}}; } 
    } 
}