Swagger/Swashbuckle list acceptable values?

2019-07-03 08:13发布

问题:

I have implemented Swashbuckle/Swagger on my Web API application successfully, but am not happy with the output.

One of my web api methods (An enterprise event logging tool) accepts a JSON object of a Complex object value.

The issue is that the parameters are listed as string objects when there is a selected list of acceptable values that can be used. I have set default values so that if something incorrect is sent, I set to default.

I guess I could add other service calls that return the acceptable values, but I would rather not.

I did implement the schema portion on Swashbuckle to set a valid "example" object, but it only listed one of probably a hundred different combinations.

The best example I can give of the problem is below:

EnterpriseEvent {
   EventType (string, optional),
   SourceSystem (string, optional),
   Company (string, optional),
   Interface (string, optional),
   TransactionType (string, optional),
   EventDateTime (string, optional),
   EventXML (Array[Object], optional),
   Operation (string, optional),
   LoggingLevel (string, optional)
}

The acceptable values for SourceSystem would be something like "Accounting" or "Payments" or "Portal". While the Acceptable values for Company could be "Sub Company 1" or "Partner 1".

Is there something I can add to Swashbuckle/Swagger to get this in the output somewhere?

回答1:

The simplest solution would be to to change properties from string type to enum, like:

// original    
public class EnterpriseEvent {
   public string SourceSystem { get; set; }
}

// change
 public class EnterpriseEvent {
   public SourceSystemType SourceSystem { get; set; }
}
public enum SourceSystemType {  
   Accounting,
   Payments
}   

However enums with spaces are a pain. There is a standard .NET mechanism of handling those (decorating enum members with EnumMember attribute), however swashbuckle doesn't take that into an account.

[DataContract]
public enum CompanyType
{
    [EnumMember(Value = "Partner 1")]
    Partner1,
    [EnumMember(Value = "Sub Company 1")]
    SubCompany1
}

See https://github.com/domaindrivendev/Swashbuckle/pull/563/files

So you can get modified version of swashbuckle (with the fix above). Or if you don't want to have custom swashbuckle build (I can relate to that) you can leave your model as it is and implement your "own" schema provider like this:

GlobalConfiguration.Configuration 
  .EnableSwagger(c =>
  {
    c.CustomProvider((defaultProvider) => new CustomSwaggerProvider(defaultProvider));
  });       

public class CustomSwaggerProvider: ISwaggerProvider
{
  private readonly ISwaggerProvider m_DefaultProvider;
  public CustomSwaggerProvider(ISwaggerProvider defaultProvider)
  {
    m_DefaultProvider = defaultProvider;
  }

  public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
  {
    // grab the default schema
    var result = m_DefaultProvider.GetSwagger(rootUrl, apiVersion);
    // adjust
    result.definitions["EnterpriseEvent"]
     .properties["SourceSystem"]
     .@enum = new string[] { "Enum with space 1", "Enum with space 2" };

    return result;
  }
}

EDIT:

If I understand your comment you don't have the string as enums configured in web api. Here is quick how-to:

protected void Application_Start() {
  GlobalConfiguration.Configure((config) => {
    config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
      new Newtonsoft.Json.Converters.StringEnumConverter());
  });
}