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

ASP.NET Core 6如何通过URI扩展名设置Accept请求头值?

在ASP.NET Core 6中实现URI扩展名映射Accept头的方案

现成配置方案:路由令牌转换器

ASP.NET Core 6提供了RouteTokenTransformerConvention机制,无需手动正则处理就能实现从URI扩展名提取格式并修改请求Accept头的功能,步骤如下:

1. 实现自定义路由令牌转换器

创建转换器类,处理扩展名与媒体类型的映射,同时设置请求的Accept头:

public class FormatRouteTransformer : IInboundParameterTransformer, IOutboundParameterTransformer
{
    private readonly Dictionary<string, string> _formatMappings = new()
    {
        ["json"] = "application/json",
        ["protobuf"] = "application/protobuf",
        ["xml"] = "application/xml"
    };

    // 出站转换(生成URL时使用,可选实现)
    public string TransformOutbound(object value)
    {
        if (value is string mediaType)
        {
            return _formatMappings.FirstOrDefault(kv => kv.Value == mediaType).Key;
        }
        return null;
    }

    // 入站转换:解析扩展名并设置Accept头
    public ValueTask<string> TransformAsync(HttpContext httpContext, string value)
    {
        if (_formatMappings.TryGetValue(value, out var mediaType))
        {
            httpContext.Request.Headers.Accept = mediaType;
        }
        return ValueTask.FromResult<string>(null); // 无需修改路由参数,返回null即可
    }
}

2. 注册转换器并配置服务

在Program.cs中添加路由转换器的注册,同时确保已添加所需的输出格式化程序:

var builder = WebApplication.CreateBuilder(args);

// 添加控制器及所需格式化程序
builder.Services.AddControllers(options =>
{
    options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
    // 若使用Protobuf,需添加对应格式化程序(如Google.Protobuf.AspNetCore.ProtobufOutputFormatter)
});

// 注册路由令牌转换器
builder.Services.AddRouting(options =>
{
    options.ConstraintMap.Add("format", typeof(FormatRouteTransformer));
});

var app = builder.Build();

app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();

3. 修改控制器路由模板

在控制器路由末尾添加{format:format}参数,匹配URI中的扩展名:

[ApiController]
[Route("my/resource{format:format}")]
public class ResourceController : ControllerBase
{
    [HttpGet]
    public IActionResult GetResource()
    {
        var resource = new { Id = 1, Name = "Sample Resource" };
        return Ok(resource);
    }
}

此时请求http://localhost:5000/my/resource.json时,转换器会自动将Accept头设为application/json,ASP.NET Core会自动调用对应的输出格式化程序。

替代方案:中间件处理

如果不想修改现有路由结构,可以编写中间件拦截请求,解析URI扩展名并设置Accept头:

public class FormatExtensionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly Dictionary<string, string> _formatMappings = new()
    {
        ["json"] = "application/json",
        ["protobuf"] = "application/protobuf",
        ["xml"] = "application/xml"
    };

    public FormatExtensionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var path = context.Request.Path.Value;
        var extension = Path.GetExtension(path);
        if (!string.IsNullOrEmpty(extension) && extension.StartsWith("."))
        {
            var format = extension.TrimStart('.');
            if (_formatMappings.TryGetValue(format, out var mediaType))
            {
                context.Request.Headers.Accept = mediaType;
                // 可选:移除路径中的扩展名,避免路由匹配失败
                context.Request.Path = path.Substring(0, path.Length - extension.Length);
            }
        }

        await _next(context);
    }
}

// 在Program.cs中注册中间件(需放在UseRouting之前)
app.UseMiddleware<FormatExtensionMiddleware>();

这种方式无需改动现有路由规则,直接在请求到达控制器前完成扩展名解析与头设置,适合快速兼容现有客户端的场景。


内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 13:25:39