用于包装 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}}; }
}
}
我构建了一个 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
.
对于简单的 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}}; }
}
}