Can I force Azure API Management to return 400 instead of 404 when missing required field?

Viewed 530

We have an application that requires some fields to be present. If those fields aren't present we will return a 400 response explaining what is missing in a proper error message. Adding APIM to the mix complicates it a lot it seems. Since APIM know that the field is required it looks like it will short curcuit and return 404 with a generic message instead of our self explanatory message of what is wrong.

Is it a way to turn of this functionality for APIM?

2 Answers

I'm getting the same issue and I endup changing my approach. What I did was to configure it on the Application side and use FluentValidation to make the querystring parameters required. So, my model now looks something like this:

using FluentValidation;

public class UrlQueryParameters
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
}

public class UrlQueryParametersValidator : AbstractValidator<UrlQueryParameters>
{
    public UrlQueryParametersValidator()
    {
        RuleFor(o => o.PropertyA)
            .NotEmpty()
            .WithMessage("The 'PropertyA' parameter was missing or a value was not provided.");

        RuleFor(o => o.PropertyB)
            .NotEmpty()
            .WithMessage("The 'PropertyB' parameter was missing or a value was not provided.");
    }
}

The preceding code defines a couple of validation rules with custom messages for PropertyA and PropertyB properties.

Now, enable FluentValidation as the default validation mechanism for our application by adding the following code at ConfigureServices method of Startup.cs file:

public void ConfigureServices(IServiceCollection services) {
    // Rest of the code omitted for brevity
    
    services
      .AddControllers()
      .AddFluentValidation(fv => 
      { 
          fv.DisableDataAnnotationsValidation = true;
          
          // The following line registers ALL public validators in the assembly containing UrlQueryParametersValidator
          // There is no need to register additional validators from this assembly.
          fv.RegisterValidatorsFromAssemblyContaining<UrlQueryParametersValidator>(lifetime: ServiceLifetime.Singleton);
      });
}

At this point, your API endpoints should validate the required parameters from the request and APIM should not short-circuit the request by throwing 404 Not Found when you try to access /api/foo/{id}.

The reason why this works because Swashbuckle doesn't automatically import validation rules from FluentValidation. Meaning, the properties PropertyA and PropertyB won't be marked as required when viewing them in the Swagger UI. This is the downside for this approach as the required querystring parameters from the Swagger UI will not be marked as required which could be confusing to consumers. But to me, returning the correct StatusCode with meaningful message to consumers is more important and that's why I will stick to this workaround for the time being. You could try using the MicroElements.Swashbuckle.FluentValidation to altleast set/marked the parameters as required in the Swagger UI schema. But that's just about it.

I blogged about this it here: Dirty Hack on Making the Required QueryString Params to Work in Azure APIM

At API/Product/Global level policy add on-error section, use choose policy to check if operation was found or not:

<choose>
  <when condition="@(context.LastError.Source == "configuration" && context.LastError.Reason == "OperationNotFound")">
    <return-response>
      <set-status code="400" reason="Bad Request" />
    </return-response>
  </when>
</choose>
Related