Search code examples
c#asp.net-coreswagger

Messages are not displayed in HttpResponseException


I have an exception class to which I pass return codes and write an error message. I see the return code on the page, but the messages do not arrive. What could be the problem?

public AppException(HttpStatusCode httpStatusCode, string message) 
        : base(message)
    {
        throw new HttpResponseException(new HttpResponseMessage(httpStatusCode)
        {
            Content = new StringContent(message)
        });
    }
}

Throwing an exception from the service

public async Task<User> CreateAsync(User user)
{
    if (EmailExists(user.Email))
    {
        var message = string.Format($"User with id={user.Email} already exists.");
        throw new AppException(HttpStatusCode.InternalServerError, message);
    }

    ....
}

I call the service method in the controller:

/// <summary>
/// Creates a User
/// </summary>
/// <response code="201">User created</response>
/// <response code="400">Input data is invalid</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<User>> CreateAsync(User user)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var result = await _userService.CreateAsync(user);
    return Ok(result);
}

In the screenshot, I executed a request to create a user with an existing email. It showed the return code but didn't show the message. The "message" field definitely doesn't come empty to the AppException class. Checked it on debug:

enter image description here


Solution

  • You are trying to throw the expection HttpResponseException in the AppException constructor which is not the right or the recommended way to to throw excpetion. contracture are use to create the instance of the class or initialize an object.HttpResponseException gets thrown and immediately caught by ASP.NET, which generates a response based on it and sends it back to the client that's why you are not getting the correct error message.

    To fix the issue you can choose one of the below way 1)Handle exception by using middleware 2)By using controller throw exception

    Here is the code you could try:

    public class AppException : Exception
    {
        public HttpStatusCode StatusCode { get; }
    
        public AppException(HttpStatusCode statusCode, string message) 
            : base(message)
        {
            StatusCode = statusCode;
        }
    }
    

    service:

    public async Task<User> CreateAsync(User user)
    {
        if (EmailExists(user.Email))
        {
            var message = string.Format($"User with email={user.Email} already exists.");
            throw new AppException(HttpStatusCode.InternalServerError, message);
        }
    
        
    }
    

    controller:

    [HttpPost]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<User>> CreateAsync(User user)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
    
        try
        {
            var result = await _userService.CreateAsync(user);
            return Ok(result);
        }
        catch (AppException ex)
        {
            return StatusCode((int)ex.StatusCode, ex.Message);
        }
    }