繁体   English   中英

如何将自定义标头添加到 ASP.NET Core Web API 响应

[英]How to add custom header to ASP.NET Core Web API response

我正在将我的 API 从 Web API 2 移植到 ASP.NET Core Web API。 我曾经能够通过以下方式添加自定义标题:

  HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
  response.Headers.Add("X-Total-Count", count.ToString());
  return ResponseMessage(response);

如何在 ASP.NET Core Web API 中添加自定义标头?

您可以从传入的 Http RequestHttpContext ,并在调用 return 之前将您自己的自定义标头添加到Response对象。

如果您希望自定义标头持续存在并添加到跨多个控制器的所有 API 请求中,则应考虑制作一个Middleware组件来为您执行此操作,然后将其添加到Startup.cs的 Http 请求管道中

public IActionResult SendResponse()
{
    Response.Headers.Add("X-Total-Count", "20");

    return Ok();
}    

有一个简单的GET操作示例,它从某个列表返回前X条记录以及响应标头X-Total-Count count

using System;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication.Controllers
{
    [Route("api")]
    public class ValuesController : Controller
    {
        [HttpGet]
        [Route("values/{top}")]
        public IActionResult Get(int top)
        {
            // Generate dummy values
            var list = Enumerable.Range(0, DateTime.Now.Second)
                                 .Select(i => $"Value {i}")
                                 .ToList();
            list.Reverse();

            var result = new ObjectResult(list.Take(top))
            {
                StatusCode = (int)HttpStatusCode.OK
            };

            Response.Headers.Add("X-Total-Count", list.Count.ToString());

            return result;
        }
    }
}

URL 看起来像http://localhost:3377/api/values/5和结果(生成 19 个虚拟记录,因此X-Total-Count值将是 19)如下:

["Value 18","Value 17","Value 16","Value 15","Value 14"]

对于任何想要为所有请求添加自定义标头的人来说,中间件是最好的方法。 在 startup.cs 中进行一些更改,如下所示:

app.Use(async (context, next) =>
{
   context.Response.Headers.Add("X-Developed-By", "Your Name");
   await next.Invoke();
});

祝你好运。

自定义属性可能是一个好方法。

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string _value;

    public AddHeaderAttribute(string name, string value)
    {
        _name = name;
        _value = value;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_name, new string[] { _value });
        base.OnResultExecuting(context);
    }
}

然后像这样在你的 API 方法上使用它

[AddHeader("X-MyHeader", "123")]

如果你有一个共同的标题,你可以扩展这个类:

public class MySpecialHeaderAttribute : AddHeaderAttribute
{
    public MySpecialHeaderAttribute() : base("X-MyHeader", "true")
    {
    }
}

我同意@Ho3Ein 的观点

如果您想为所有请求添加自定义标头,中间件是最好的方法

但不鼓励直接在中间件中修改Resposne 来自微软文档

响应开始后对 HttpResponse 的更改,引发异常。 例如,设置标头和状态代码等更改会引发异常。

app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

因此,在中间件中添加自定义标头的更好方法是使用Response.OnStarting回调,如下所示:

app.Use(async (context, next) =>
                      {

                          context.Response.OnStarting(() =>
                              {
                                  context.Response.Headers.Add("X-Developed-By", "Your Name");
                                  return Task.FromResult(0);
                              });

                          await next();
                      }
                      );

其他中间件可能会在您设置标题后清除它们。 为确保您的标头已添加,请在发送响应之前添加它们。

app.Use(async (context, next) => {
    context.Response.OnStarting(() => {
        context.Response.Headers.Add("X-Developed-By", "Your Name");
        return Task.FromResult(0);
    });

    await next();
});

或者在真正的中间件中

public class AddHeadersMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        context.Response.OnStarting(() => {
            context.Response.Headers.Add("X-Developed-By", "Your Name");
            return Task.FromResult(0);
        });

        await next();
    }
}

FWIW,如果你有一个ApiController ,而不是一个Controller ,你可以这样做:

public class InfoController : ApiController
{
    // Without custom header
    public IHttpActionResult MyMethod(..)
    {
        var myObject= GetMyResult();
        return Ok(myObject);
    }

    // With custom header
    public IHttpActionResult MyMethod(..)
    {
        var myObject = GetMyResult();

        // inspired from https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/content-negotiation#how-content-negotiation-works
        var negotiator = Configuration.Services.GetContentNegotiator();
        var result = negotiator.Negotiate(typeof(TypeOfMyObject), Request, Configuration.Formatters);
        var msg = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new ObjectContent<TypeOfMyObject>(myObject, result.Formatter,result.MediaType.MediaType)
        };

        msg.Headers.Add("MyCustomHeader", "MyCustomHeaderValue");
        return ResponseMessage(msg);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM