it-swarm.com.de

Fügen Sie in ApiController einen benutzerdefinierten Antwortheader hinzu

Bisher hatte ich eine GET-Methode, die wie folgt aussah:

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

Dies funktionierte wie ein Zauber und es war gut. Kürzlich wurde mir jedoch gesagt, dass ich die response metadata (dh Total, Count und Last -Eigenschaften) als benutzerdefinierte Header für die Antwort anstelle des Antworthauptteils senden soll.

Ich kann nicht auf die Response vom ApiController zugreifen. Ich habe an einen Filter oder ein Attribut gedacht, aber wie erhalte ich die Metadatenwerte?

Ich kann all diese Informationen in der Antwort aufbewahren und habe dann einen Filter, der die Antwort deserialisiert, bevor sie an den Client gesendet wird, und eine neue mit den Kopfzeilen erstellt, aber das scheint mühsam und schlecht zu sein.

Gibt es eine Möglichkeit, benutzerdefinierte Kopfzeilen direkt aus dieser Methode in einer ApiController hinzuzufügen?

18
Matias Cicero

Ich habe Kommentare eingegeben, hier ist meine vollständige Antwort. 

Sie müssen einen benutzerdefinierten Filter erstellen und diesen auf Ihren Controller anwenden.

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

In Ihrem Controller 

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

Sie können in einer Methode wie folgt explizit benutzerdefinierte Kopfzeilen hinzufügen:

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

Weitere Informationen finden Sie in diesem Artikel: http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/

21
Seagull

Was Sie brauchen, ist:

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

    return base.ResponseMessage(response); 
}

Ich hoffe, das beantwortet deine Frage. 

5
Nikola

Eine einfache Lösung ist nur zu tun:

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

Im API-Controller.

4
Deepak

Sie können einen benutzerdefinierten ActionFilter verwenden, mit dem Sie benutzerdefinierte Header senden und auf den HttpContext zugreifen können:

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

Alternativ ist es besser, DelegatingHandler zu nutzen, wenn Sie dies bei jeder Antwort tun müssen. Weil es auf der Anforderungs-/Antwort-Pipeline und nicht auf der Controller-/Aktionsebene funktioniert. In meinem Fall muss ich bei jeder Antwort einige Überschriften hinzufügen, also habe ich das getan, was ich beschrieben habe. Siehe folgenden Codeausschnitt

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

}

Und Sie müssten diesen Handler in WebApiConfig hinzufügen

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