Visual Studio 中的代码分析问题

Code analysis issue in Visual Studio

请找到以下代码:

private static void HandleValidationError(ILogger logger, HttpRequestMessage requestMessage, HttpStatusCode statusCode, string message)
        {
        logger.LogError(LoggingSources.API, message);
throw new HttpResponseException(requestMessage.CreateErrorResponse(statusCode, message));
   }
            }

我遇到以下 CA 问题:

CA2000 Dispose objects before losing scope In method 'ControllerHelper.HandleValidationError(ILogger, HttpRequestMessage, HttpStatusCode, string)', object 'HttpRequestMessageExtensions.CreateErrorResponse(requestMessage, statusCode, message)' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'HttpRequestMessageExtensions.CreateErrorResponse(requestMessage, statusCode, message)' before all references to it are out of scope. Tasks.Application.Web.API ControllerHelper.cs 106

上述函数的调用者是:

public static void CheckForValidDelimitedIntegerInput(ILogger logger, HttpRequestMessage request, char delimiter, string input)
        {
            if (!string.IsNullOrEmpty(input))
            {
                try
                {
                    string[] idList = input.Split(delimiter);
                    for (int i = 0; i < idList.Length; i++)
                    {
                        int result;
                        if (!int.TryParse(idList[i], out result) || result <= 0)
                        {
                            HandleValidationError(logger, request, HttpStatusCode.BadRequest, InvalidIntegerOrShort);
                        }
                    }
                }
                catch (HttpResponseException)
                {
                    throw;
                }
            }
            else
            {
                HandleValidationError(logger, request, HttpStatusCode.BadRequest, InvalidParameter);
            }
        }

我之前试过Whosebugpost但是没有成功

阅读 this article to understand the "Dispose Pattern". Also, read this post to see when an object should be disposed. In your particular case, it looks like an anti-pattern 以在调用者仍有对函数的引用时处理函数的参数。

为了解决您收到的警告,requestMessage.CreateErrorResponse(...) 创建了一个 HttpResponseMessage,它实现了 IDisposable。在方法 returns 之前,这超出了范围(因为您没有对它进行引用)。这意味着代码分析工具发现从未调用此对象上的 Dispose

编辑:

要解决此问题,只需删除 using 指令,并按如下方式简化代码。

private static void HandleValidationError(ILogger logger, HttpRequestMessage requestMessage, HttpStatusCode statusCode, string message)
{
    logger.LogError(LoggingSources.API, message);
    throw new HttpResponseException(requestMessage.CreateErrorResponse(statusCode, message));
}

这似乎对我有用。不过,这会将对象留给调用者处理。

编辑:

啊哈!我发现这个 stack overflow post 似乎是您的确切问题。为了完整起见,它基本上说您不需要处理 HttpResponseMessage 对象。但是,如果您改为使用构造函数,则已经抑制了此警告,因此您无需自己抑制它。

试试这个:

private static void HandleValidationError(ILogger logger, HttpRequestMessage requestMessage, HttpStatusCode statusCode, string message)
{
    logger.LogError(LoggingSources.API, message);
    throw new HttpResponseException(new HttpResponseMessage(statusCode){
        ReasonPhrase = message
    });
}

注意:因为我无法重现这个问题,所以我无法测试以确保它有效。

经过一番分析,我终于找到了答案。

private static void HandleValidationError(ILogger logger, HttpRequestMessage requestMessage, HttpStatusCode statusCode, string message)
    {
        logger.LogError(LoggingSources.API, message);
        using (var errorResponse = requestMessage.CreateErrorResponse(statusCode, message))
        {
            throw new HttpResponseException(errorResponse);
        }
    }    

这将解决 CA 问题。我还要感谢约翰的帮助。

使用 using 会导致 500 内部服务器错误。

我的解决方案是 RegisterForDispose 所以它变成了:

var errorResponse = requestMessage.CreateErrorResponse(statusCode, message));
this.request.RegisterForDispose(errorResponse);
throw new HttpResponseException(errorResponse);

您仍然需要抑制 CA2000 警告,但我相信这是正确的处理方式,因此 CA2000 需要允许这种处理模式。