如何在ASP.NET Core中通过属性为OpenAPI规范添加控制器方法链接?
实现SwaggerGen关联端点生成OpenAPI Links
可以实现你要的功能,但Swashbuckle.AspNetCore(即SwaggerGen)并没有内置你设想的[Link]属性,需要自己定义属性并配合Swagger过滤器来完成OpenAPI 3.0规范中links字段的生成。
步骤1:自定义LinkAttribute属性
先定义一个用来标记端点关联的特性,支持指定目标Action和参数映射:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class LinkAttribute : Attribute { // 目标控制器的Action名称 public string ActionName { get; } // 当前响应体中用来填充目标参数的字段名 public string ParameterName { get; } // 可选的链接描述 public string? Description { get; set; } public LinkAttribute(string actionName, string parameterName) { ActionName = actionName; ParameterName = parameterName; } }
步骤2:实现Swagger操作过滤器
编写一个IOperationFilter,用来解析LinkAttribute并生成对应的OpenAPI Links:
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; public class LinkOperationFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { // 获取当前Action上的所有LinkAttribute var linkAttributes = context.MethodInfo.GetCustomAttributes<LinkAttribute>(); if (!linkAttributes.Any()) return; // 初始化Links集合 operation.Links ??= new Dictionary<string, OpenApiLink>(); foreach (var linkAttr in linkAttributes) { // 找到目标Action的描述信息 var targetAction = context.ApiDescription.ActionDescriptor.EndpointMetadata .OfType<ControllerActionDescriptor>() .FirstOrDefault(ad => ad.ActionName == linkAttr.ActionName); if (targetAction == null) continue; // 获取目标Action的相对路径 var targetPath = context.ApiDescriptionsProvider.ApiDescriptions .First(ad => ad.ActionDescriptor == targetAction) .RelativePath; if (string.IsNullOrEmpty(targetPath)) continue; // 构建OpenAPI Link对象 var openApiLink = new OpenApiLink { OperationId = targetAction.ActionName, Description = linkAttr.Description ?? $"获取刚创建的资源,使用响应中的{linkAttr.ParameterName}字段", // 映射参数:从当前响应体中取值填充目标接口的userId参数 Parameters = new Dictionary<string, OpenApiAny> { { "userId", new OpenApiString($"$response.body#{linkAttr.ParameterName}") } }, Server = operation.Servers.FirstOrDefault() }; // 将Link添加到当前操作的Links集合中 operation.Links.Add($"Get{linkAttr.ParameterName}", openApiLink); } } }
步骤3:注册过滤器到SwaggerGen
在项目的Program.cs(或Startup.cs)中,把自定义过滤器注册到SwaggerGen配置里:
var builder = WebApplication.CreateBuilder(args); // 添加Swagger服务 builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "用户管理API", Version = "v1" }); // 注册自定义的Link操作过滤器 c.OperationFilter<LinkOperationFilter>(); }); // ...其他中间件配置 var app = builder.Build(); // 启用Swagger UI if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.Run();
步骤4:在控制器中使用[Link]属性
现在就可以像你期望的那样,给CreateUser方法添加属性关联GetUser接口:
[HttpPost] [Route("~/users")] [ProducesResponseType(typeof(ResponseObject<UserId>), StatusCodes.Status200OK)] // 关联GetUser方法,用响应体中的UserId字段填充目标接口的userId参数 [Link(nameof(GetUser), "UserId", Description = "获取刚创建的用户详情")] public async Task<IActionResult> CreateUser(...) { // 创建用户的业务逻辑 } [HttpGet] [Route("~/users/{userId}")] [ProducesResponseType(typeof(ResponseObject<User>), StatusCodes.Status200OK)] public async Task<IActionResult> GetUser(...) { // 获取用户详情的业务逻辑 }
最终效果
生成的OpenAPI规范中,CreateUser接口的200响应会包含links字段,指向GetUser接口,并且指定userId参数从当前响应体的UserId字段取值,完全符合OpenAPI 3.0的Links规范。
内容的提问来源于stack exchange,提问作者NoddyCode
相关产品推荐
相关产品推荐

