Search code examples
c#asp.net-web-apiswagger-uiswashbuckle

Grouping of API methods in documentation - is there some custom attribute


I have controller like

public class UserController : ApiController
{
  [Route("api/user")]
  IHttpActionResult GetUser() { ... }
}

public class ResumeController : ApiController
{
  [Route("api/user/resumes")]
  IHttpActionResult GetResumes() { ... }
}

Which on swagger generates output like enter image description here

Is there a way (besides overriding default implementation by rolling out your own ISwaggerProvider or merging two controllers into one) to enforce the group name ? Something like

public class UserController : ApiController
{
  [Route("api/user")]
  [MagicalAttributeName(Group="User")]
  IHttpActionResult GetUser() { ... }
}

public class ResumeController : ApiController
{
  [Route("api/user/resumes")]
  [MagicalAttributeName(Group="User")]
  IHttpActionResult GetResumes() { ... }
}

Solution

  • There is a way - although there is no magic attribute - you can change default rules of grouping in swagger startup configuration in order to introduce your very own custom attribute.

    GlobalConfiguration.Configuration 
     .EnableSwagger(c => {
       c.GroupActionsBy(apiDesc => apiDesc
         .GetControllerAndActionAttributes<MethodGroupAttribute>().Any() ?
            apiDesc.GetControllerAndActionAttributes<MethodGroupAttribute()
            .First().GroupName :
            apiDesc.ActionDescriptor.ControllerDescriptor.ControllerName);
     });
    
    
    /// <summary>
    /// Forces method to be displayed within specified group, regardless of controller
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class MethodGroupAttribute : Attribute
    {
        /// <summary>
        /// Group name
        /// </summary>
        public string GroupName { get; private set; }
    
        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="groupName"></param>
        public MethodGroupAttribute(string groupName)
        {
            if (string.IsNullOrEmpty(groupName))
            {
                throw new ArgumentNullException("groupName");
            }
            GroupName = groupName;
        }
    }
    

    Usage:

    [Route("api/user")]
    [MethodGroup("User")]
    IHttpActionResult GetUser() { ... }