You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Core中通过属性为OpenAPI规范添加控制器方法链接?

可以实现你要的功能,但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();

现在就可以像你期望的那样,给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:55:23