Asp.Net core Swashbuckle set operationId

2019-08-21 08:26发布

How can I set swagger operationId attribute in Asp.Net Core 2.1 project? According to this post I should use SwaggerOperationAttribute but I cannot find it in Swashbuckle.AspNetCore library. Also there is an IOperationFilter

  public interface IOperationFilter
  {
    void Apply(Operation operation, OperationFilterContext context);
  }

and I can't find any implementations for swagger generation purposes.

3条回答
闹够了就滚
2楼-- · 2019-08-21 09:11

You can enable annotation on swagger with the Swashbuckle.AspNetCore.Annotations nuget package. (https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#swashbuckleaspnetcoreannotations)

Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a SwaggerOperationAttribute.

[HttpPost]

[SwaggerOperation(
    Summary = "Creates a new product",
    Description = "Requires admin privileges",
    OperationId = "CreateProduct",
    Tags = new[] { "Purchase", "Products" }
)]
public IActionResult Create([FromBody]Product product)
查看更多
劫难
3楼-- · 2019-08-21 09:27

There are 2 other options without having to write any extra code or add extra dependency like Swashbuckle.AspNetCore.Annotations

Option 1: Convention based - SwaggerGen has an option to set CustomOperationIds. So you can simply set it to use ControllerName_HttpMethod like this:

services.AddSwaggerGen(c =>
{
    c.CustomOperationIds(e => $"{e.ActionDescriptor.RouteValues["controller"]}_{e.HttpMethod}");
    c.SwaggerDoc("v1", new Info { Title = "Test API", Version = "v1" });
});

This will add operationIds to all your methods, following ControllerName_HttpMethod convention.

Option 2: ActionFilter/Attribute based - you can configure each Action method (as you'd do with SwaggerOperation action filter by simple adding a Name property to your HTTP verb action filter like this:

[HttpPost(Name="Post_Person")]
[ProducesResponseType(200)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
public async Task<ActionResult<Response>> PostAsync([FromBody]Request request)
{
    Response result = await _context.PostAsync(request);
    return Ok(result);
}

This works exactly like [SwaggerOperation(OperationId = "Post_Person")] but without the need of EnableAnnotations

查看更多
该账号已被封号
4楼-- · 2019-08-21 09:27

Finally, I came to this solution:

public class SwaggerOperationNameFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        operation.OperationId = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
            .Union(context.MethodInfo.GetCustomAttributes(true))
            .OfType<SwaggerOperationAttribute>()
            .Select(a => a.OperationId)
            .FirstOrDefault();
    }
}

[AttributeUsage(AttributeTargets.Method)]
public sealed class SwaggerOperationAttribute : Attribute
{
    public SwaggerOperationAttribute(string operationId)
    {
        OperationId = operationId;
    }

    public string OperationId { get; }
}

// Startup.cs
services.AddSwaggerGen(c =>
{
    ...
    c.OperationFilter<SwaggerOperationNameFilter>();
};

[HttpGet("{id:int}")]
[SwaggerOperation("GetById")]
public async Task<IActionResult> Get(int id)
{
    ...
}

But it still seems to me that I've reinvented the wheel.

查看更多
登录 后发表回答