c# - 如何让我的 asp.netcore JsonResult 序列化到我的动作控制器内的主体,以便我可以捕获异常并计时其执行?
问题描述
我有一个如下所示的控制器操作:
[HttpGet]
public async Task<IActionResult> Query(CancellationToken ct, string query)
{
var sw = new StopWatch();
sw.Start();
try {
IEnumerable<object> shortInfo = someObject.Query(query, ct).Distinct();
return new JsonResult(
// note that the next line still returns an IEnumerable, and does not execute yet
// shortInfo has not yet begun enumeration either.
shortInfo.Select(si => SomeSelectFunction(si))
);
}
catch (Exception e)
{
return StatusCode(499);
}
finally
{
sw.Stop();
Debug.WriteLine($"Query took {sw.ElapsedMilliseconds / 1000.0} sec");
}
}
当我运行我的代码时,执行的时间非常短,并且还没有发生任何枚举。此外,我无法捕获 someObject.Query 由于取消而引发的任何异常,也无法捕获由于 SomeSelectFunction() 引发的任何异常,这也可能非常复杂。
这样做的好处是 JsonResult 被枚举并直接序列化到响应正文中,而无需物化一堆对象。
相反,我将 JsonResult 中的行更改为
shortInfo.Select(si => SomeSelectFunction(si)).ToList()
然后我可以正确计时并捕获异常,但代价是在序列化之前实现整个列表。
问题:有什么方法可以得到延迟序列化的好处,并且仍然能够对查询函数的总持续时间进行计时。有没有办法将结果序列化到这个函数内部的响应体中,并且仍然将 json 作为 json 返回?
解决方案
考虑使用过滤器实现,允许您挂钩执行之前和之后的顺序。例如
public class EndpointTimingMetricFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items["timer"] = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (!(context.HttpContext.Items["timer"] is Stopwatch sw))
{
return;
}
sw.Stop();
var endpointId = GetEndpointId(context);
Debug.WriteLine($"Query took {sw.ElapsedMilliseconds / 1000.0} sec to execute for endpoint {endpointId}");
}
private static string GetEndpointId(ActionContext context)
{
var template = context.ActionDescriptor.AttributeRouteInfo.Template;
var method = context.HttpContext.Request.Method;
return method + " - " + template;
}
}
然后,这为您提供了一个横切关注点,您可以将其应用于任何端点,并将此样板代码保留在您的主控制器操作之外。
OnActionExecuted 是在构建结果/响应之后,所以应该给你你所追求的,
图片来自:https ://www.c-sharpcorner.com/article/working-with-filters-in-asp-net-core-mvc/
推荐阅读
- javascript - 如何在 React 中调用渲染之前重置状态?
- amazon-web-services - 如何创建开发和生产 Cloudfront 密钥对?
- android - 如何访问 Helper 匿名类上的 View 对象
- javascript - 如何在浏览器中使用 JS 访问 Azure Blob 存储
- flutter - 有没有更好的方法来比较一个日期和另一个日期?
- android - 是否可以在我的应用程序中启动另一个应用程序并使用 Xamarin 点击另一个应用程序的特定坐标
- web-scraping - rvest 忽略 url 不存在并继续抓取
- postgresql - 如果我用返回 1 行的简单查询替换 where 子句中的数字文字,PostgreSQL 不会正确修剪分区
- python - 如何在取列的平均值之前更新行值?
- c++ - 链表中的构造函数、析构函数和 = 运算符的问题