Search code examples
c#azureazure-functionsresponse

Returning 40x response in Azure Isolate function


I have a problem which is very similar to this StackOverflow issue. i have the below .net 6.0 isolate function. when i call it in postman i can see the catch statement is being executed but the response is always 200.

[Function("Enquiry")]
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
        {
            try
            {
                var a = new ErrorResponseModel
                {
                    ErrorType = ErrorResponseTypeEnum.ModelValidation
                };

                a.ErrorMessages.Add("This is a test");

                throw new InvalidModelException(a);
            }
            catch (InvalidModelException inv)
            {
                
                var res = req.CreateResponse();
                res.StatusCode = HttpStatusCode.BadRequest;                
                await res.WriteAsJsonAsync(inv.ErrorResponseModel);

                return res;
            }
}

postman

Nothing in MS documentation suggests req.CreateResponse(); should only have 20x response. i do not want to use ActionResult like the above StackOverflow link as i could not find anything within MS documentation that if ActionResult is a supported return type. actually in MS official documentation. it also seems IActionResult object is still under preview.

Updated information as requested, ErrorResponseModel

[DataContract]
    public class ErrorResponseModel
    {
        [DataMember]
        [JsonConverter(typeof(StringEnumConverter))]
        public ErrorResponseTypeEnum ErrorType { get; set; }

        [DataMember]
        public List<string> ErrorMessages { get; set; }

        public ErrorResponseModel() => ErrorMessages = new List<string>();

    }

    public enum ErrorResponseTypeEnum { ModelValidation, MissingParameter, FileLocked }

InvalidModelException

public class InvalidModelException : Exception
    {
        private readonly ErrorResponseModel _errorResponseModel;

        public ErrorResponseModel ErrorResponseModel => _errorResponseModel;

        public InvalidModelException(ErrorResponseModel errorResponseModel) 
        {
            _errorResponseModel = errorResponseModel;
        }
    }

Solution

  • When you use Write it's overwriting the status code you set. In order to provide details in the bad request response, you need to do the following:

            catch (InvalidModelException inv)
            {
                var c = new
                {
                    inv.Message,
                    inv.StackTrace
                };
                var response = req.CreateResponse(HttpStatusCode.BadRequest);
                using var writer = new StreamWriter(response.Body, Encoding.UTF8, leaveOpen: true);
                await writer.WriteAsync(JsonSerializer.Serialize(c));
                return response;
            }
    

    PS: you can't serialize the InvalidModelException exception directly. It works with NewtonSoft.Json but fails with System.Text.Json