在ApiController中添加自定义响应标头

Mat*_*ero 22 c# asp.net http-headers asp.net-web-api asp.net-web-api2

到现在为止,我的GET方法如下所示:

protected override async Task<IHttpActionResult> GetAll(QueryData query)
{
     // ... Some operations

     //LINQ Expression based on the query parameters
     Expression<Func<Entity, bool>> queryExpression = BuildQueryExpression(query);

     //Begin to count all the entities in the repository
     Task<int> countingEntities = repo.CountAsync(queryExpression);

     //Reads an entity that will be the page start
     Entity start = await repo.ReadAsync(query.Start);

     //Reads all the entities starting from the start entity
     IEnumerable<Entity> found = await repo.BrowseAllAsync(start, queryExpression);

     //Truncates to page size
     found = found.Take(query.Size);

     //Number of entities returned in response
     int count = found.Count();

     //Number of total entities (without pagination)
     int total = await countingEntities;

     return Ok(new {
          Total = total,
          Count = count,
          Last = count > 0 ? GetEntityKey(found.Last()) : default(Key),
          Data = found.Select(e => IsResourceOwner(e) ? MapToOwnerDTO(e) : MapToDTO(e)).ToList()
     });
}
Run Code Online (Sandbox Code Playgroud)

这就像一个魅力,它很好.不过,我最近告诉发送响应的元数据(也就是Total,CountLast属性)为响应自定义标题,而不是响应主体.

我无法管理Response从ApiController 访问.我想到了过滤器或属性,但我如何获取元数据值?

我可以将所有这些信息保存在响应中,然后有一个过滤器,它会在发送到客户端之前反序列化响应,并创建一个带有标题的新响应,但这看起来很麻烦和糟糕.

有没有办法直接从这个方法添加自定义标题ApiController

Sea*_*ull 25

您可以在类似的方法中显式添加自定义标头:

[HttpGet]
[Route("home/students")]
public HttpResponseMessage GetStudents()
{
       // Get students from Database

       // Create the response
        var response = Request.CreateResponse(HttpStatusCode.OK, studends);

        // Set headers for paging
        response.Headers.Add("X-Students-Total-Count", studends.Count());

       return response;
}
Run Code Online (Sandbox Code Playgroud)

欲了解更多信息,请阅读本文:http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/


You*_*suf 20

我已经输入了评论,这是我的完整答案.

您需要创建自定义过滤器并将其应用于控制器.

public class CustomHeaderFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
       var count = actionExecutedContext.Request.Properties["Count"];
       actionExecutedContext.Response.Content.Headers.Add("totalHeader", count);
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的控制器中

  public class AddressController : ApiController
        {
            public async Task<Address> Get()
            {
               Request.Properties["Count"] = "123";
            }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这很好用,但这是正确的方法吗?我的元数据应该是响应的属性,而不是请求.我的意思是,它可以作为一种解决方案,但它在概念上是否合适? (4认同)
  • 这看起来像是我的双重工作.您可以[直接]添加标题(/sf/answers/3184265381/) (2认同)
  • 就我而言,我发现这是在标头中返回响应数据的最佳解决方案,但您必须小心操作过滤器获取数据的位置。我必须获取您正在处理的请求的数据,我到处寻找该请求独有的数据存储,我唯一能找到的是“context.Request.Properties”表,这很可能为什么@Yousuf 使用它。请记住,处理操作时“context.Response”对象不存在,因此“context.Request”似乎是您可以像这样存储数据的唯一地方。 (2认同)

nka*_*fov 8

你需要的是:

public async Task<IHttpActionResult> Get() 
{ 
    var response = Request.CreateResponse();
    response.Headers.Add("Lorem", "ipsum");

    return base.ResponseMessage(response); 
}
Run Code Online (Sandbox Code Playgroud)

我希望这回答了你的问题.


Dee*_*pak 8

简单的解决方案是只做:

HttpContext.Current.Response.Headers.Add("MaxRecords", "1000");
Run Code Online (Sandbox Code Playgroud)

  • 派生 ApiController 的控制器中不会出现 HttpContext。 (4认同)

Raj*_*sar 8

或者,如果您需要对每个响应执行某些操作,最好利用 DelegatingHandler。因为它将在请求/响应管道上工作,而不是在控制器/操作级别上工作。在我的情况下,我必须在每个响应中添加一些标题,所以我做了我所描述的。请参阅下面的代码片段

public class Interceptor : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        response.Headers.Add("Access-Control-Allow-Origin", "*");
        response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,PUT,OPTIONS");
        response.Headers.Add("Access-Control-Allow-Headers", "Origin, Content-Type, X-Auth-Token, content-type");
        return response;
    }

}
Run Code Online (Sandbox Code Playgroud)

并且您需要在 WebApiConfig 中添加此处理程序

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MessageHandlers.Add(new Interceptor());
        }
    } 
Run Code Online (Sandbox Code Playgroud)