1

I'm working on a microservice which is a proxy/façade for Personio, allowing us to filter and otherwise manipulate their API's own responses.

We have a couple endpoints which will allow authorized users to receive Personio's responses after redacting them. These endpoints allow the consumer to include any query parameters and forward them to Personio "as-is", for Personio to decide whether it supports the parameter, ignores the parameter, or causes the server to vomit.

We use Swagger to document our own endpoints.

As we get the consumer's query parameters from Request.Query at a deeper level within the code, for example:

    /// <summary>
    /// This endpoint acts as a proxy for Personio's Employee records, filtering the results only to include Montage employees..
    /// Any query parameters passed to this endpoint will be passed "as-is" to Personio.
    /// At this time (2021 December 22), Personio only supports "limit", "offset", and "email" on the Employee endpoint
    /// While Personio itself does not require the "limit" parameter, this is known to cause performance issues, so if the consumer do not
    /// provide this, we will set this to the maximum value of 200.
    /// @see also: https://developer.personio.de/reference#employees-1
    /// </summary>
    [Authorize(Roles = MontageReadRole)]
    [ProducesResponseType(typeof(PagedList<JObject>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(List<ErrorMessage>), StatusCodes.Status403Forbidden)]
    [HttpGet("Employees/Montage")]
    public Task<IActionResult> GetMontageEmployees(CancellationToken cancellationToken) =>
        GetMontageData(_personioEmployeeService.GetMontageEmployees, cancellationToken);

    private async Task<IActionResult> GetMontageData<T>(Func<IQueryCollection, CancellationToken, TryAsync<RequestResponse<T>>> getData, CancellationToken cancellationToken)
    {
        try
        {
            IActionResult result = null;
            _ = await getData(Request.Query, cancellationToken)
                .Match(
                    Succ: response =>
                        result = Ok(response),

                    Fail: exception =>
                        result = _controllerErrorHandler.CreateBadRequestObject(new()
                        {
                            Status = StatusCodes.Status422UnprocessableEntity,
                            Type = "Unprocessable Entity",
                            Detail = exception.Message
                        })
                )
                .ConfigureAwait(false);
            return result;
        }
        catch (UnauthorizedAccessException ex)
        {
            return _controllerErrorHandler.CreateAuthenticationFailureResponse(ex);
        }
    }

... they are not part of the endpoint's method signature, so Swagger has no reasonable way of knowing that this is supported.

Is there any way (e.g. through an attribute) I can allow consumers to include additional query parameters?

Or, at the very least, is there some way I can include some sort of description on the endpoint to tell the consumer "hey, we support this!"? (FYI, the <summary> above does not appear on the swagger page.)

Brian Kessler
  • 2,187
  • 6
  • 28
  • 58
  • 1
    You can use the SwaggerOperation attribute to provide additional API documentation (https://medium.com/c-sharp-progarmming/configure-annotations-in-swagger-documentation-for-asp-net-core-api-8215596907c7) – fbede Jan 25 '22 at 14:45
  • @fbede, cheers for this. FYI, SwaggerOperationAttribute is obsolete; we should use OpenApiOperationAttribute instead. ;-) – Brian Kessler Jan 25 '22 at 15:29
  • I think it isn't deprecated in Swashbuckle's swagger lib, but it is in NSwag's, so you are probably using that one. Please upvote the comment if it was helpful. – fbede Jan 25 '22 at 15:38
  • @fbede, already upvoted the comment, but to be honest, it was not as helpful as I hoped.... I don't see either the summary or description displayed on my Swagger page even though the attribute exists.... Maybe I need something else somewhere for Swagger to actually do something with the information? (Double checking docs) – Brian Kessler Jan 25 '22 at 15:40
  • You might have to enable annotations to make descriptions show up on your swagger page, like this: services.AddSwaggerGen(opt => { opt.EnableAnnotations(); }) – fbede Jan 27 '22 at 13:07
  • @fbede annotiations, but it did not seem to work.... maybe this is not compatible with whatever Swagger library we are using. :-/ – Brian Kessler Jan 27 '22 at 13:45

0 Answers0