Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate parameter output in Swagger

Update: I'm starting to wonder if this is due to a bug:

https://github.com/domaindrivendev/Swashbuckle/issues/590

But the workaround suggested there does not seem to solve my problem.


I am using Swashbuckle to generate API documentation for a C# ASP.NET Web API project.

My target is to allow the following as valid URL:

/endpoint/items/123/foo?param2=bar

With a required parameter (param1) set to "foo" and an optional parameter (param2) set to "bar". I would like both parameters contained inside a single C# parameter object. (with other optional parameters like param3 and so on). Several endpoints will use identical parameters and I would like to have a single object representing the parameters.

The details of Swagger/Swashbuckle are mostly a black box to be, and I'm unable to figure this out. I'm getting duplicates in the parameter list.

Sample code to reproduce the problem:

    // This endpoint is generating documentation the way I would like.
    [HttpGet]
    [Route("endpoint1/items/{id}/{param1}")]
    public string GetDataForParameters(int id, string param1, string param2 = null, string param3 = null)
    {
        return string.Format("Params: {1}, {2}, {3}", id, param1, param2, param3);
    }

    // This endpoint has the structure I would like, but I get duplicates for param1 in the documentation.
    [HttpGet]
    [Route("endpoint2/items/{id}/{param1}")]
    public string GetDataForParameters(int id, [FromUri(Name = "")]MyParams myParams)
    {
        return string.Format("Params: {1}, {2}, {3}", id, myParams.Param1, myParams.Param2, myParams.Param3);
    }

    public class MyParams
    {
        public string Param1 { get; set;}
        public string Param2 { get; set;}
        public string Param3 { get; set;}
    }

With the second method, I receive the parameters inside a single object. But Swagger displays a duplicate entry for the "param1".

Screenshot: Swagger duplicate parameter

How can I make Swagger/Swashbuckle not display the second entry for "param1"?


The reason for having this structure is that I have multiple endpoints that return different types of data, but they use common parameters. Some of the parameters are required (and a prt of the ID) so we would like to include those in the URL, with optional parameters in the querystring. I would prefer the common parameter object should include both required and optional parameters.

Sample code created with Visual Studio 2015 update 1. Default ASP.NET Web API project. Adding the code above to the generated ValuesController.cs. Installed package Swashbuckle 5.3.1 + dependencies.

like image 540
PMBjornerud Avatar asked Feb 18 '16 09:02

PMBjornerud


People also ask

What is explode in swagger?

explode (true/false) specifies whether arrays and objects should generate separate parameters for each array item or object property.


1 Answers

Update: Found a workaround. It's ugly:

  1. Introduce an explicit duplicate parameter in the method.
  2. Add JsonIgnore attribute to the duplicate properties in the parameter object.

Swagger will then pick up the method parameter and documentation for this one. ASP.Net will assign parameters to BOTH the method parameter and the parameter object, allowing the code to use the parameter object.

    /// <param name="param1">URL parameters must be documented on this level.</param>
    [HttpGet]
    [Route("endpoint2/items/{id}/{param1}")]
    public string GetDataForParameters(int id, string param1, [FromUri(Name = "")]MyParams myParams)
    {
        // the param1 method parameter is a dummy, and not used anywhere.
        return string.Format("Params: {1}, {2}, {3}", id, myParams.Param1, myParams.Param2, myParams.Param3);
    }

    public class MyParams
    {
        /// <summary>
        /// Cannot add documentation here, it will be ignored.
        /// </summary>
        [JsonIgnore]
        public string Param1 { get; set;}
        /// <summary>
        /// This is included. Querystring parameters can be documented in this class.
        /// </summary>
        public string Param2 { get; set;}
        public string Param3 { get; set;}
    }

I will not use this approach, it will be too confusing for any other developer reading the code. So unfortunately, Swagger/Swashbuckle has in pratice forced me to change my (fully working) code in order to generate documentation.

Unless anyone can suggest a proper solution I think the best solution is to have plain method parameters.

like image 101
PMBjornerud Avatar answered Sep 26 '22 17:09

PMBjornerud