[英]Wrapping a complex object as Response with ResultFilterAttribute
In my controller, I've inherited from a ControllerBase which there is a Result method that is used to wrap the response into a ResponseBase object like this:在我的 controller 中,我从 ControllerBase 继承了一个Result方法,用于将响应包装到ResponseBase object 中,如下所示:
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public abstract class BaseApiController : ControllerBase
{
protected async Task Result<T>(T content, Dictionary<string, string> headers = null,
HttpStatusCode statusCode = HttpStatusCode.OK, string contentType =
"application/json")
{
Response.StatusCode = (int)statusCode;
Response.ContentType = contentType;
if (headers != null)
{
foreach (var header in headers)
{
Response.Headers.Add(header.Key, header.Value);
}
}
var data = Encoding.UTF8.GetBytes
(MySerializer.Serialize(new ResponseBase<T> { Data = content }));
await Response.Body.WriteAsync(data.AsMemory(0, data.Length));
}
}
And the ResponseBase is like: ResponseBase就像:
public class ResponseBase
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public List<ErrorBase> Errors { get; set; }
}
public class ResponseBase<T> : ResponseBase
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public T Data { get; set; }
}
public class ErrorBase
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string FieldName { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string ErrorMessage { get; set; }
}
And finally my controller:最后是我的 controller:
[ApiVersion("1")]
public class ConfigurationController : BaseApiController
{
private readonly IConfigurationService _configurationService;
public ConfigurationController(IConfigurationService configurationService)
{
_configurationService = configurationService;
}
[HttpGet("getData")]
public async Task GetData()
{
await Result(await _configurationService.GetRelatedData());
}
}
Now, the question here is, how can I wrap my response into a ResponseBase with a help of ResultFilterAttribute without explicitly calling the Result method in the ControllerBase现在,这里的问题是,如何在ResultFilterAttribute的帮助下将我的响应包装到ResponseBase中,而不显式调用ControllerBase中的Result方法
I've tried to use a ResultFilter to wrap my response but I couldn't find any sample to do this.我尝试使用 ResultFilter 来包装我的响应,但我找不到任何示例来执行此操作。 I've also read this solution but didn't help.我也读过这个解决方案,但没有帮助。
I appreciate any help.我很感激任何帮助。
ResultFilter
.实施ResultFilter
。In short,简而言之,
1.1. 1.1。 Get the values of context.Result
such as StatusCode
, ContentType
, Value
.获取context.Result
的值,例如StatusCode
、 ContentType
、 Value
。
1.2. 1.2. Bind the Value
to the root class ( ResponseBase
).将Value
绑定到根 class ( ResponseBase
)。
1.3. 1.3. Lastly, produce a new Response.最后,产生一个新的响应。
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
Dictionary<string, string> headers = null;
int statusCode = (int)HttpStatusCode.OK;
string contentType = "application/json";
var responseBaseType = typeof(ResponseBase<>).MakeGenericType(typeof(object));
dynamic? responseBase = Activator.CreateInstance(responseBaseType);
var result = context.Result as ObjectResult;
if (result?.Value == null)
{
await next();
return;
}
if (result.StatusCode != null)
statusCode = (int)result.StatusCode;
if (result.ContentTypes != null
&& result.ContentTypes.Any())
contentType = result.ContentTypes[0];
if (statusCode == (int)HttpStatusCode.OK)
responseBase.Data = result.Value;
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(responseBase));
context.HttpContext.Response.StatusCode = statusCode;
context.HttpContext.Response.ContentType = contentType;
await context.HttpContext.Response.Body.WriteAsync(data.AsMemory(0, data.Length));
}
IActionResult
type.修改API方法,返回IActionResult
类型的值。[HttpGet("getData")]
public async Task<IActionResult> GetData()
{
return new ObjectResult(await _configurationService.GetRelatedData());
}
ResultFilter
as global filter to controller in Program.cs .在Program.cs中将 ResultFilter 注册为ResultFilter
的全局过滤器。builder.Services.AddControllers(options =>
{
options.Filters.Add<ResultFilter>();
});
Note: The ResultFilter
isn't a complete solution, while implementing you should consider different scenarios of IActionResult
such as BadRequestObjectResult
etc.注意: ResultFilter
不是一个完整的解决方案,在实现时您应该考虑IActionResult
的不同场景,例如BadRequestObjectResult
等。
Reference参考
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.