首页 > 解决方案 > .NET Core Web API - 如何从 ActionResult 获取响应信息

问题描述

我有一个 WebAPI 核心端点方法,我使用内部库 (RequestLogManager) 来保存来自和传入请求的请求和响应数据。

因为我想记录响应代码和正文,所以我将 ActionResult 存储在方法结束时返回的变量中(而不是从方法中的多个位置返回)。例子:

    // This is a contrived method to illustrate the issue.
    
    [Route("test/actionresult/{testParam:int}")]
    [HttpGet]
    public async Task<ActionResult> GetTestActionResult(int testParam)
    {
        ActionResult actionResult = Ok(); // Default

        // Log Incoming Request
        int requestlogid = await RequestLogManager.LogIncomingRequestAsync("API - GetTestActionResult", Request);

        switch (testParam)
        {
            case 204:
                actionResult = NoContent();
                break;

            case 404:
                actionResult = NotFound();
                break;

            case 500:
                actionResult = StatusCode(StatusCodes.Status500InternalServerError, "An Error Occurred!");
                break;

            default:
                break;
        }

        // Log Outgoing Response
        RequestLogManager.LogResponseForRequestNoWait(requestlogid, ??? ResponseBody ???, ??? ResponseCode ???);

        return actionResult;
    }

在我的方法结束时,如何从 ActionResult 获取响应代码和正文的值以记录?

标签: c#asp.net-core-webapi

解决方案


中间件是处理请求和响应日志的方法。您可以自定义中间件,它们可以连接到HTTP管道,您可以在中间件实现中执行日志记录。这种方法可以帮助您在全球范围内进行。

创建中间件以拦截请求和响应

// Request Logging middleware
public class RequestLoggingMiddleware
{
    private RequestDelegate _next;
    public RequestLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // Logic to log your request. Can be accessed via "context.Request"
        await _next.Invoke(context);
    }
}
// Response Logging Middleware
public class ResponseLoggingMiddleware
{
    private RequestDelegate _next;
    public ResponseLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // observe the Invoke() method being called first
        await _next.Invoke(context)
        // This is where your logging logic goes. For eg., you can capture 404 as below
        if(context.Response.StatusCode == 404)
        {
            // log the 404 and do whatever you want to do on a 404 here.
        }
    }
}

将中间件连接到HTTP管道

这非常简单,可以通过以下代码语句完成。

// Within the Configure() method of Startup.cs
app.UseMiddleware<ResponseLoggingMiddleware>();
app.UseMiddleware<RequestLoggingMiddleware>();

连接中间件的顺序在这里很重要。有关中间件排序和一般中间件的更多信息,请点击此处

更新:

创建自定义属性以处理端点级别的日志记录

public class LoggingAttribute : Attribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // This method is called just right after the completion of the 
        // execution of the action method. Status Code can be obtained as shown below
        // response logging based on status code goes here.
        var result = context.Result;
        var response = context.HttpContext.Response.StatusCode;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // This method is called before the action method is invoked.
        // Access the request using context.HttpContext.Request
        // and include the logging logic where
        var request = context.HttpContext.Request;            
    }
}

现在可以根据需要将此属性添加到控制器内的操作方法中,如下所示。

[HttpGet]
[LoggingAttribute]
public ActionResult<IEnumerable<string>> Get()
{
    // ...other code
}

推荐阅读