Asp.Net Core 6 Web API - How to return only 400 Bad requests

Cenk 996 Reputation points
2023-06-26T17:11:56.0233333+00:00

Hi guys,

I have an ASP.NET core Web API that I am calling 3rd party web services. I have exception middleware in order to log exceptions and return 500 responses to hide the details from the user.

Here is where I am calling this 3rd party web service.

public static async Task<HttpResponseMessage?> CallOrder(string url, string token, WatsonOrderRequest watsonOrderRequest, IConfiguration iConfiguration)
        {
            HttpResponseMessage? response;
            try
            {
                //HTTPWebRequest
                var request = (HttpWebRequest)WebRequest.Create(iConfiguration.GetSection("Ezpin:Url").Value + url);

                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                request.KeepAlive = false;
                request.Headers.Add("Authorization", "Bearer " + token);

                //Create a list of your parameters
                var postParams = new List<KeyValuePair<string, string>>(){
                    new KeyValuePair<string, string>("sku", watsonOrderRequest.sku.ToString()) ,
                    new KeyValuePair<string, string>("quantity", watsonOrderRequest.quantity.ToString()),
                    new KeyValuePair<string, string>("pre_order", watsonOrderRequest.pre_order.ToString()),
                    new KeyValuePair<string, string>("price", watsonOrderRequest.price),
                    new KeyValuePair<string, string>("reference_code", watsonOrderRequest.reference_code.ToString())
                };

                var formUrlEncodedContent = new FormUrlEncodedContent(postParams);
                var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();

                await using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
                {
                    await streamWriter.WriteAsync(urlEncodedString);
                }

                var httpResponse = (HttpWebResponse)(await request.GetResponseAsync());
                response = new HttpResponseMessage
                {
                    StatusCode = httpResponse.StatusCode,
                    Content = new StreamContent(httpResponse.GetResponseStream()),
                };
            }
            catch (WebException ex)
            {
                //Identify error details
                var resp = await new StreamReader(ex.Response!.GetResponseStream()).ReadToEndAsync();
                dynamic obj = JsonConvert.DeserializeObject(resp);
                var detail = obj.detail;
                var code = obj.code;
                response = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(detail.ToString(), System.Text.Encoding.UTF8, "application/json") };
                throw new Exception(response.ToString());
            }

            return response;
        }


Here is the exception middleware; it logs the errors and returns 500 for hiding exception details from the user.

public class ExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private static IConfiguration _configuration;
        private static ILogger<ExceptionMiddleware> _logger;
        
        public ExceptionMiddleware(RequestDelegate next, IConfiguration configuration, ILogger<ExceptionMiddleware> logger)
        {
            _next = next;
            _configuration = configuration;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(httpContext, ex);
            }
        }

        private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            try
            {
                _logger.LogError("Web API Exception Handler Error: " + exception);
                await using var sqlConnection =
                    new SqlConnection(_configuration.GetSection("ConnectionStrings:OyunPalasDbContext").Value);
                await using var cmd =
                    new SqlCommand(
                        "INSERT INTO [dbo].[APIError] ([Message],[RequestMethod],[RequestUri],[TimeUtc]) VALUES (@Message, @RequestMethod, @RequestUri, @TimeUtc)",
                        sqlConnection);
                sqlConnection.Open();

                cmd.Parameters.AddWithValue("@Message", exception.Message);
                cmd.Parameters.AddWithValue("@TimeUtc", DateTime.Now);
                cmd.Parameters.AddWithValue("@RequestUri", context.Request.Path.ToString());
                cmd.Parameters.AddWithValue("@RequestMethod", context.Request.Method.ToString());

                if (exception.InnerException != null)
                {
                    cmd.Parameters.AddWithValue("@Message", exception.Message +" " + exception.InnerException);
                    _logger.LogError("Web API Exception Handler Inner Error: " + exception.InnerException);
                }

                

                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                _logger.LogError("Web API Exception Handler insert error: " + e.Message);
                
            }
            
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            await context.Response.WriteAsync(new ErrorDetails()
            {
                StatusCode = context.Response.StatusCode,
                Message = "Internal Server Error."
            }.ToString());
        }
    }

If this 3rd party service returns 400 bad requests, I would like to return it to the user. How can I do it?

Thank you.

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,500 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
326 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Zhi Lv - MSFT 32,141 Reputation points Microsoft Vendor
    2023-06-27T06:35:28.1533333+00:00

    Hi @Cenk

    If this 3rd party service returns 400 bad requests, I would like to return it to the user. How can I do it?

    In the API method, you can check the httpResponse.StatusCode, if the status code is 400, you can return a BadHttpRequestExceptionexception. Then, in the ExceptionMiddleware's HandleExceptionAsync method, you can check whether the exception is a BadHttpRequest exception or not, then based on the result to return different error message. Code like this:

            private async Task HandleExceptionAsync(HttpContext context, Exception exception)
            {
                if (exception is BadHttpRequestException badRequestException)
                {
                    //400 exception.
                    context.Response.ContentType = "application/json";
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    await context.Response.WriteAsync(new ErrorDetails()
                    {
                        StatusCode = context.Response.StatusCode,
                        Message = "Bad Request Error from the custom middleware."
                    }.ToString());
                }
                else
                {
                    //return 500 error
                    context.Response.ContentType = "application/json";
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    await context.Response.WriteAsync(new ErrorDetails()
                    {
                        StatusCode = context.Response.StatusCode,
                        Message = "Internal Server Error from the custom middleware."
                    }.ToString());
    
                } 
            }
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.