Search code examples
c#swashbuckle

Swagger c# ProduceResponseType for Wrapped AutoWrapper Response


As all of our responses are wrapped in AutoWrapper,

what is the best way to tell swagger that they are wrapped by AutoWrapper ?

Instead of adding this on every controller methods ?

[ProducesResponseType( 200, Type = typeof( AutoWrapper<IEnumerable<WeatherForecast>> ) )]

Solution

  • You can minimize your effort and create your own API Convention and apply it to your assembly in Startup.cs.

    Test model:

    public class MyTestModel
    {
        public string SomeString { get; set; }
        public int SomeInteger { get; set; }
        public bool SomeBool { get; set; }
    }
    

    Response Wrapper (inspired from here):

    public class AutoWrapper<T>
    {
        public int StatusCode { get; set; }
        public string Message { get; set; }
        public T Result { get; set; }
    }
    

    Convention Class:

    public static class MyAppConventions
    {
        [ProducesResponseType(200, Type = typeof(AutoWrapper<List<MyTestModel>>))]
        [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
        public static void Weather()
        {
        }
    }
    

    Controller:

    [HttpGet]
    public List<MyTestModel> GetWeather()
    {
        List<MyTestModel> models = new List<MyTestModel>
        {
            new MyTestModel
            {
                SomeString = "Hello world!",
                SomeInteger = 101,
                SomeBool = true
            }
        };
    
        return models;
    }
    

    Lastly, in the Startup, you need to add a decorator:

    [assembly: ApiConventionType(typeof(MyAppConventions))]
    namespace NameSpace
    {
        public class Startup
        {
          //stuff...
        }
    }
    

    In Swagger, this will get illustrated as:

    Swagger

    Schema view

    This approach however some-what relies on a naming standard being established across your controller method names in order to minimize the amount of code you'll need to write in the Convention class. You can use the ApiConventionNameMatch attribute to match on a suffix, prefix, any method name (ignores parameters), and exact name (parameter or method must match). For example, you can cover all of your controller methods in your project that are named Get(int id) by declaring the following in the convention class:

    [ProducesResponseType(200, Type = typeof(AutoWrapper<YourObject>))]
    [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
    public static void Get(int id)
    {
    }