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 需要允许这种处理模式。
请找到以下代码:
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 需要允许这种处理模式。