Add a custom response header in ApiController

我们两清 提交于 2019-12-09 04:39:23

问题


Until now, I had a GET method that looked like the following:

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()
     });
}

This worked like a charm and it was good. However, I was told recently to send the response metadata (that is, Total, Count and Last properties) as response custom headers instead of the response body.

I cannot manage to access the Response from the ApiController. I thought of a filter or attribute, but how would I get the metadata values?

I can keep all this information on the response and then have a filter that will deserialize the response before being sent to the client, and create a new one with the headers, but that seems troublesome and bad.

Is there a way to add custom headers directly from this method on an ApiController?


回答1:


I have entered comments, here is my complete answer.

You will need to create a custom filter and apply that to your controller .

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

In your Controller

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



回答2:


You can explicitly add custom headers in a method like so:

[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;
}

For more information read this article: http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/




回答3:


What you need is:

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

    return base.ResponseMessage(response); 
}

I hope this answers your question.




回答4:


Simple solution is to do just:

HttpContext.Current.Response.Headers.Add("MaxRecords", "1000");



回答5:


Alternatively, it’s better to leverage DelegatingHandler if it is something you need to perform on every response. Because it will work on the request/response pipeline and not on the controller/action level. In my case I must add some headers with every response, so I did what I described. See code snippet below

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;
    }

}

And you would be requiring to add this handler in WebApiConfig

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MessageHandlers.Add(new Interceptor());
        }
    } 



回答6:


You can use a custom ActionFilter that will allow you to send custom headers and access the HttpContext:

public class AddCustomHeaderFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
       actionExecutedContext.Response.Content.Headers.Add("name", "value");
    }
}


来源:https://stackoverflow.com/questions/32017686/add-a-custom-response-header-in-apicontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!