【问题标题】:Adding an Attribute for Response processing为响应处理添加属性
【发布时间】:2020-10-01 15:45:08
【问题描述】:

使用 C#,Net Core 3.1

我想知道是否有人可以提供帮助。 我想添加“中间件”,但我认为我的要求需要一个属性,因为我只想对特定的 API 操作有选择地执行此操作。 在将响应发送到请求客户端之前,如何对响应进行一些处理(例如签署消息并将其添加到响应标头)?

例如

    [HttpGet]
    [PostResponseProcessAttribute]
    public IActionResult GetFoo(int id) {
        return MyFoo();
    }

所以对于这个 GetFoo Action,我想做这样的事情:

public class PostResponseProcessAttribute : Attribute {
    public OnBeforeSendingResponse(){
      var response = Response.Content.ReadAsStringAsync;
     //do some stuff
      response.Headers.Add(results from stuff)
    }
}

这是我需要实现的属性吗?我需要覆盖的功能是什么? 此外,一个关键位是响应的格式和状态将被发送到客户端(即通过其他格式化中间件处理等) - 这对于签名很重要,因为任何差异都意味着客户端正在验证响应不同的版本,因此总是失败。

谢谢

【问题讨论】:

  • 您不能在运行时将任何数据传递给属性。因此,您应该编写将完成所有工作并设置所需标头的中间件。您可以在您的案例中使用属性仅用于标记需要处理的方法。

标签: c# asp.net-core middleware


【解决方案1】:

最后,我写了这个:

public sealed class AddHeadersRequiredAttribute : Attribute
{
}

public class AddHeadersMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext context)
    {
        await using var memory = new MemoryStream();
        var originalStream = context.Response.Body;
        context.Response.Body = memory;

        await _next(context);

        memory.Seek(0, SeekOrigin.Begin);
        var content = await new StreamReader(memory).ReadToEndAsync();
        memory.Seek(0, SeekOrigin.Begin);

        // Now you can manipulate with content
        var attribute = GetAddHeadersRequiredAttributeFromMatchedAction(context);
        if (attribute != null)
            context.Response.Headers.Add("X-Header-1", content);

        await memory.CopyToAsync(originalStream);
        context.Response.Body = originalStream;
    }

    private Attribute GetAddHeadersRequiredAttributeFromMatchedAction(HttpContext context)
    {
        var endpoint = context.GetEndpoint();
        var controllerActionDescriptor = endpoint?.Metadata.GetMetadata<ControllerActionDescriptor>();
        return controllerActionDescriptor?.MethodInfo.GetCustomAttribute<AddHeadersRequiredAttribute>();
    }
}

您可以使用AddHeadersRequiredAttribute 标记控制器方法。然后像这样在Startup.Configure 方法中使用中间件

app.UseMiddleware<AddHeadersMiddleware>();

【讨论】:

  • 你可以像这样在 UseMiddleware 传递它:app.UseMiddleware&lt;AddHeadersMiddleware&gt;(app.ApplicationServices.GetService&lt;IService&gt;()); 并将IService 添加到中间件构造函数参数中。如果只在中间件中使用IService,则应将其注册为单例,因为中间件将被创建一次。
  • 让你的例子发挥作用!谢谢你。确保在 Startup Configure() 中尽早添加它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 2021-05-05
  • 2023-03-18
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多