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

ASP.NET Core中带内容类型后缀的ETag生成方案咨询

ASP.NET Core Web API 生成自定义ETag并确定序列化格式化程序

一、确定当前使用的序列化格式化程序

在ASP.NET Core中,Web API会根据请求的Accept标头、服务配置的输出格式化器集合,自动选择合适的格式化器序列化返回的C#对象。你可以通过以下两种方式获取最终选中的格式化器:

1. 全局动作过滤器方式

创建自定义动作过滤器,在OnActionExecuted阶段提取返回结果并确定格式化器:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;

public class ETagFilter : IAsyncActionFilter
{
    private readonly IOutputFormatterSelector _formatterSelector;

    public ETagFilter(IOutputFormatterSelector formatterSelector)
    {
        _formatterSelector = formatterSelector;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var executedContext = await next();

        // 仅处理返回ObjectResult的接口
        if (executedContext.Result is ObjectResult objectResult && objectResult.Value != null)
        {
            var formatterContext = new OutputFormatterWriteContext(
                executedContext.HttpContext,
                (stream, encoding) => new StreamWriter(stream, encoding),
                objectResult.DeclaredType ?? objectResult.Value.GetType(),
                objectResult.Value);

            // 获取最终选中的格式化器
            var selectedFormatter = _formatterSelector.SelectFormatter(
                formatterContext, 
                objectResult.Formatters, 
                objectResult.ContentTypes);

            // 根据格式化器确定内容类型后缀
            string contentTypeSuffix = selectedFormatter switch
            {
                JsonOutputFormatter => "json",
                XmlSerializerOutputFormatter => "xml",
                _ => "unknown"
            };

            // 生成符合要求的ETag(标准ETag需包裹双引号)
            var etagValue = $"\"{Guid.NewGuid()}_{contentTypeSuffix}\"";
            executedContext.HttpContext.Response.Headers.ETag = etagValue;
        }
    }
}

2. 单个控制器动作内处理

如果仅需在特定接口中实现,可直接在动作内获取格式化器:

[HttpGet]
public IActionResult GetSampleData()
{
    var data = new { Id = 1, Title = "Sample Content" };
    var objectResult = new ObjectResult(data);

    var formatterContext = new OutputFormatterWriteContext(
        HttpContext,
        (stream, encoding) => new StreamWriter(stream, encoding),
        typeof(object),
        data);

    var formatterSelector = HttpContext.RequestServices.GetRequiredService<IOutputFormatterSelector>();
    var selectedFormatter = formatterSelector.SelectFormatter(
        formatterContext, 
        objectResult.Formatters, 
        objectResult.ContentTypes);

    string suffix = selectedFormatter is JsonOutputFormatter ? "json" : "unknown";
    Response.Headers.ETag = $"\"{Guid.NewGuid()}_{suffix}\"";

    return objectResult;
}

二、注册并启用过滤器

将过滤器注册到服务容器,可全局启用或针对特定控制器启用:

// Program.cs 全局注册
builder.Services.AddControllers(options =>
{
    options.Filters.Add<ETagFilter>();
});

// 或在单个控制器上标记启用
[ServiceFilter(typeof(ETagFilter))]
public class DataController : ControllerBase
{
    // 接口逻辑...
}

若需依赖ETag做缓存验证,确保已配置响应缓存中间件:

builder.Services.AddResponseCaching();
app.UseResponseCaching();

三、与旧ASP.NET Framework实现的对比

旧ASP.NET Framework中通常通过ActionFilterAttribute获取ObjectContent的格式化器:

// 旧框架实现示例
public class ETagFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response.Content is ObjectContent objectContent)
        {
            string suffix = objectContent.Formatter is JsonMediaTypeFormatter ? "json" : "xml";
            var etag = new EntityTagHeaderValue($"\"{Guid.NewGuid()}_{suffix}\"");
            actionExecutedContext.Response.Headers.ETag = etag;
        }
    }
}

ASP.NET Core的等效逻辑核心差异:

  • 用IOutputFormatterSelector替代旧的ObjectContent.Formatter获取逻辑
  • 通过OutputFormatterWriteContext模拟格式化器选择流程
  • 保持生成带内容类型后缀的ETag逻辑,确保内容类型变更时旧缓存自动失效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:47:38