Add a custom response header in ApiController

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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, students);
    
        // Set headers for paging
        response.Headers.Add("X-Students-Total-Count", students.Count());
       
       return response;
}

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

Method 2

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

Method 3

Simple solution is to write just this:

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

Method 4

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.

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

Method 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");
    }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x