2015-08-14 3 views
9

До сих пор я был метод GET, который был похож на следующее:Добавить пользовательский заголовок ответа в ApiController

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

Это работало как шарм, и это было хорошо. Тем не менее, мне недавно сказали, чтобы отправить ответ метаданные (то есть Total, Count и Last) в качестве ответных пользовательских заголовков вместо тела ответа.

Я не могу получить доступ к Response от ApiController. Я думал о фильтре или атрибуте, но как бы получить значения метаданных?

Я могу хранить всю эту информацию в ответе, а затем фильтр, который будет десериализовать ответ перед отправкой клиенту и создать новый с заголовками, но это кажется хлопотным и плохим.

Есть ли способ добавить пользовательские заголовки непосредственно из этого метода на ApiController?

+1

Должно быть так же просто, как [это] (http://stackoverflow.com/questions/13487012/mvc-4-web-api-add-custom-response-http-header) – Andrei

+0

@Andrei У меня нет свойство «HttpContext», но у меня есть «ActionContext». Однако свойство 'Response' этого объекта является« null », и я не могу работать с ним. –

+0

вам нужно использовать ActionContext.Request.CreateResponse(), чтобы на самом деле создать ответ, а затем установить значения в ответ как строго типизированный объект, а не строки – harishr

ответ

10

Я Введенные комментарии, вот мой полный ответ.

Вам нужно будет создать собственный фильтр и применить его к контроллеру.

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

В вашем контроллере

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

Это работает отлично, но это правильный способ сделать это? Мои метаданные должны быть свойством ответа, а не запроса. Я имею в виду, это работает как решение, но концептуально ли оно правильно? –

+2

Это выглядит как двойная работа для меня. Вы можете добавить заголовок [непосредственно] (https://stackoverflow.com/a/45489505/2156743) – Nikola

+0

@Nikola, но затем вы потеряете строго типизированный ответ, который OP не использовал, но по-прежнему является вариантом с этим подходом , Я работаю над проектом web-api и не использую сильные типы, вызывая проблемы - для одного мы не можем легко создать правильную разметку. Избегайте возвращать нетипизированные ответы, если вы можете –

-2

Вы можете использовать собственный ActionFilter, который позволит вам отправлять собственные заголовки и доступ к HttpContext:

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

Но как бы получить« значения »заголовков? –

+0

Интересные вопросы. Похоже, вы можете установить свойство Request.Properties ["Count"] = "123" в контроллере и использовать его в фильтре. – Yousuf

+0

В фильтре вы можете получить к нему доступ actionContext.Request.Properties ["Count"] – Yousuf

8

Вы можете явно добавлять пользовательские заголовки в способе, как так:

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

Дополнительную информацию можно найти в этой статье: http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/

+0

Я делаю это, но заголовки разделяются – weagle08

+1

@ weagle08 Проходит ли ваш запрос через прокси? Если это так, вы можете прочитать это: http://stackoverflow.com/questions/20820572/under-what-conditions-are-http-request-headers-removed-by-proxies – Seagull

+0

Работал для меня, но не прокси-сервер, вовлеченный в наше соединение – Darren

0

Что вы необходимо:

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

    return base.ResponseMessage(response); 
} 

Я надеюсь, что это ответит на ваш вопрос.

Смежные вопросы