1

Please find the below code:

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

I am getting the below CA issue :

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

Caller of the above function is:

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);
            }
        }

I tried the stackoverflow earlier post Do I need to dispose an HttpResponseException from Request.CreateResponse()? But it did not work out.

Community
  • 1
  • 1
Varun
  • 597
  • 7
  • 26
  • 2
    You don't need to call `Dispose` in the `finally` block. It's wrapped in a `using`, it'll get disposed. – Jonesopolis Jul 02 '15 at 13:38
  • Yeah I know. But still I am getting the same CA issue. – Varun Jul 02 '15 at 13:41
  • 2
    Are you sure you want to dispose `requestMessage` in the method? It's being passed in; shouldn't the calling method handle the life cycle? – Wyatt Earp Jul 02 '15 at 13:46
  • You are disposing the `HttpRequestMessage` passed to the method, but you are not disposing the `HttpRequestMessage` created by calling `requestMessage.CreateErrorResponse`. – mbeckish Jul 02 '15 at 14:06
  • Maybe put `logger.LogError(LoggingSources.API, message);` inside the try block. – Dzienny Jul 02 '15 at 14:26
  • I have updated the question. Do you guys have any solution ? – Varun Jul 02 '15 at 14:52
  • possible duplicate of [Do I need to dispose an HttpResponseException from Request.CreateResponse()?](http://stackoverflow.com/questions/20688999/do-i-need-to-dispose-an-httpresponseexception-from-request-createresponse) – Frank Bryce Jul 02 '15 at 15:42

3 Answers3

1

Read 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 to dispose an argument to a function, when the caller still has a reference to it.

To address the warning that you are getting, requestMessage.CreateErrorResponse(...) creates an HttpResponseMessage, which implements IDisposable. This is falling out of scope (because there are no references you make to it), before the method returns. This means the code analysis tool sees that Dispose on this object is never called.

EDIT:

To fix this issue, simply remove the using directive, and simplify your code as follows.

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

This seemed to work for me. This will leave disposing the objects to the caller, though.

EDIT:

Aha! I found this stack overflow post which seems to be your exact issue. For completeness, it basically says that you don't need to dispose of the HttpResponseMessage object. However, if you use the constructor instead, there is already a suppression of this warning so you don't need to suppress it yourself.

Try this:

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
    });
}

Note: because I could not reproduce this issue I was unable to test to make sure that this works.

Community
  • 1
  • 1
Frank Bryce
  • 8,076
  • 4
  • 38
  • 56
1

Finally after some analysis I found the answer.

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);
        }
    }    

This will fix the CA issue. And also I want to appreciate John for his help.

Varun
  • 597
  • 7
  • 26
  • 2
    Is it possible that you could still be accessing `errorResponse` when handling his exception later? If that's the case, then it's possible that this will throw an exception when it tries to access the disposed object. – Frank Bryce Jul 02 '15 at 16:55
  • 1
    hmmm yeah but that case will not apply here I think. – Varun Jul 02 '15 at 16:57
1

Using using makes it 500 Internal Server error.

My solution is RegisterForDispose so it becomes:

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

You still need to suppress the CA2000 warning, but I believe this is the right way to dispose, so the CA2000 needs to allow this dispose pattern.

ChrisTorng
  • 742
  • 7
  • 18
  • You can exclude types and derived types in editorconfig, see: https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2000 dotnet_code_quality.CA2000.excluded_type_names_with_derived_types = HttpRequestMessage – Gunnar Már Óttarsson Feb 17 '21 at 22:05