如何从IAsyncActionFilter返回自定义Response类型?
我在C#中有一批可通过属性封装相似逻辑的函数,当前要实现的包装器需返回一个代表服务器响应的自定义Response类型。Response类定义如下:
public class Response { public int StatusCode { get; set; } public string Message { get; set; } }
待包装的示例方法:
void SentRequest() { Request(parameter: "simple text"); }
我尝试用如下继承IAsyncActionFilter的特性类来包装该方法并生成响应值:
class StorageServiceFilter : IAsyncActionFilter { private Response _response; public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { await next(); _response.StatusCode = 200; _response.Message = "Upload successful"; } }
现在我想知道能否返回这个_response?我了解ActionExecutingContext.Result属性,但它仅能返回IActionResult类型,不符合我的需求。
补充说明:IAsyncActionFilter仅支持返回Task类型的OnActionExecutionAsync方法,无法使用Task<T>作为返回类型。
可以通过两种方式实现返回自定义Response的需求:
1. 将自定义Response包装为IActionResult返回
既然ActionExecutedContext.Result仅接受IActionResult类型,可将自定义Response对象包装为JsonResult(或其他适配业务场景的IActionResult实现),既满足过滤器要求,也能输出预期的响应结构:
class StorageServiceFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 执行原Action方法逻辑 var resultContext = await next(); // 实例化并填充自定义Response var response = new Response { StatusCode = 200, Message = "Upload successful" }; // 将Response包装为JsonResult,覆盖原响应 resultContext.Result = new JsonResult(response) { StatusCode = response.StatusCode }; } }
注意:需使用next()返回的ActionExecutedContext设置Result,这是Action方法执行完成后修改响应的正确时机;原代码中_response未初始化,直接赋值会触发空引用异常,必须先实例化对象。
2. 修改Action方法的返回值(适用于方法返回Response的场景)
如果待包装方法本身设计为返回Response类型,可直接在过滤器中修改返回值:
首先调整待包装方法:
Response SentRequest() { Request(parameter: "simple text"); return new Response(); // 返回空对象,由过滤器填充内容 }
然后修改过滤器逻辑:
class StorageServiceFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var resultContext = await next(); // 检查并获取Action返回的Response对象 if (resultContext.Result is ObjectResult objectResult && objectResult.Value is Response response) { response.StatusCode = 200; response.Message = "Upload successful"; } } }
这种方式依赖框架自动将Response包装为ObjectResult,过滤器仅需修改该对象的属性即可完成响应内容填充。
内容的提问来源于stack exchange,提问作者isolo

