Generated OpenAPI schema is not conforming to 2.0 spec

I’ve just updated to v.4.5.10 and I’m noticing two issues that are making the schema generated by the openapi plugin invalid.

First, the parameters array defining my request contain both ‘form’ and ‘body’ parameters. I did not specify ‘form’ in the ApiMemeberAttribute on the properties. Further - I’ve notices that I can have both ‘form’ and ‘formData’ depending on how I set the ‘DisableAutoDtoInBodyParam’ and that doesn’t seem right. I want body only. I wrote a filter to remove the form parameters but it seems like a hack.

Second, in the spec, in the response object the description is a required field. My default responses do not have a description. How can I add it? Again I’ve used a filter to ‘hack’ one in but it is just that - a hack.

Relevant section of JSON:

 "parameters": [
          {
            "name": "MID",
            "in": "path",
            "type": "string",
            "required": true
          },
          {
            "name": "UserName",
            "in": "form",
            "type": "string",
            "required": true
          },
          {
            "name": "Type",
            "in": "form",
            "type": "string",
            "required": true,
            "enum": [
              "Merchant",
              "API"
            ]
          },
          {
            "name": "body",
            "in": "body",
            "schema": {
              "$ref": "#/definitions/GatewayCredentialRequest"
            }
          }
        ],
        "responses": {
          "default": {
            "schema": {
              "$ref": "#/definitions/GatewayCredentialResponse"
            }
          }
        },

Request DTO:

[Route("/gatewaycredential/{MID}", "POST, OPTIONS")]
    [DataContract]
    public class GatewayCredentialRequest : IReturn<GatewayCredentialResponse>
    {
        [ApiMember(IsRequired = true, ExcludeInSchema = true, ParameterType = "path")]
        [DataMember]
        public string MID { get; set; }

        [ApiMember(IsRequired = true)]
        [DataMember]
        public string UserName { get; set; }

        [ApiMember(IsRequired = true)]
        [ApiAllowableValues("Type", Values = new string[] { "Merchant", "API" })]
        [DataMember]
        public string Type { get; set; }
    }

I can provide more details if needed. I also had to modify the swagger-ui javascript code to get oauth2 within swagger to work with servicestack’s JWT provider. Seemed like those should work together by default…

To remove “form” parameters you can add ParamType="model" into [ApiMember] attribute

[ApiMember(IsRequired = true, ParameterType = "model")]
[ApiAllowableValues("Type", Values = new string[] { "Merchant", "API" })]
[DataMember]
public string Type { get; set; }

Having “form” parameter type when type is not specified explicity is not correct in terms of Open API specification because it should be “formData”, so we’ll fix this.

To add decsription to response DTO you have to add an [Api(..)] attribute on the response class.

[Api("Description of the response")]
public class GatewayCredentialResponse
{
    public string Result { get; set; }
}

Bearer tokens are not supported in Open API 2.0 specification, they are supported only from version 3.0 and you have to manually add Bearer prefix in Swagger UI auth dialog, but if you have a javascript patch for Swagger UI v2.2.10 which will adds Bearer to token headers after authentication it will be appreciated.

Thank you! Modifying the ApiMemberAttributes with the model value is working for me. Side comment - it would be nice if the comments in the assembly were up to date:

Same with the ApiAttribute on the response DTO - works perfectly.

For the swagger-ui, I’m using a password flow in oatuh2 so it is supported in general - not apikeys.
i.e.

 api.SecurityDefinitions.Add("token_auth", new OpenApiSecuritySchema()
                    {
                       Type = "oauth2",
                       Flow = "password",
                       TokenUrl = MyConfig.OriginURI + "/v1/auth",
                       Scopes = new Dictionary<string, string>()
                    });

The key changes I had to make were:

  1. Adding an Accept header explict as ‘application/json’ on the token request. By default the request was being sent with Accept: */* which led the built-in auth endpoint to return a HTML Report view although the verb was POST not GET.
  2. Modifying the token property in the js from ‘access_token’ to ‘bearerToken’
  3. Manually adding the security definition to the schema and referencing it in the corresponding paths via the ApiDeclarationFilter.

If there’s a different way to accomplish the above, I’d love the feedback. I’ve got what I need to work sufficiently well with the minor changes referenced above.