it-swarm.com.de

Fügen Sie allen Antworten in der Web-API einen benutzerdefinierten Header hinzu

Eine einfache Frage, und ich bin sicher, dass sie eine einfache Antwort hat, aber ich kann sie nicht finden.

Ich verwende WebAPI und möchte einen benutzerdefinierten Header an alle Antworten zurücksenden (Datum und Uhrzeit des Servers, das von einem Dev zu Synchronisierungszwecken angefordert wurde).

Ich habe derzeit Probleme, ein klares Beispiel dafür zu finden, wie ich an einer Stelle (über global.asax oder an einer anderen zentralen Stelle) einen benutzerdefinierten Header für alle Antworten erhalten kann.


Antwort angenommen, hier ist mein Filter (fast das gleiche) und die Zeile, die ich zur Register-Funktion der WebApi-Konfig hinzugefügt habe.

HINWEIS: Das DateTime-Zeug ist NodaTime, kein echter Grund war nur daran interessiert, es anzusehen.

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        actionExecutedContext.Response.Content.Headers.Add("ServerTime", Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime()).ToString());
    }

Config Line:

config.Filters.Add(new ServerTimeHeaderFilter());
49
Modika

Dafür können Sie einen benutzerdefinierten ActionFilter (System.Web.Http.Filters) verwenden.

public class AddCustomHeaderFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
       actionExecutedContext.Response.Headers.Add("customHeader", "custom value date time");
    }
}

Sie können den Filter dann auf alle Aktionen Ihres Controllers anwenden, indem Sie ihn beispielsweise in der Konfiguration in Global.asax hinzufügen:

GlobalConfiguration.Configuration.Filters.Add(new AddCustomHeaderFilter());

Sie können das Filterattribut auch auf die gewünschte Aktion ohne die globale Konfigurationszeile anwenden.

84
Tomasz Jaskuλa

Vorherige Antworten auf diese Frage beziehen sich nicht darauf, was zu tun ist, wenn Ihre Controller-Aktion eine Ausnahme auslöst. Es gibt zwei grundlegende Möglichkeiten, um dies zum Laufen zu bringen:

Einen Ausnahmefilter hinzufügen :

using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;

public class HeaderAdderExceptionFilter : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        if (context.Response == null)
            context.Response = context.Request.CreateErrorResponse(
                HttpStatusCode.InternalServerError, context.Exception);

        context.Response.Content.Headers.Add("header", "value");
    }
}

und in Ihrem WebApi-Setup:

configuration.Filters.Add(new HeaderAdderExceptionFilter());

Dieser Ansatz funktioniert, da der standardmäßige Ausnahmebehandler von WebApi die in einem Filter erstellte HttpResponseMessage sendet, anstatt eine eigene zu erstellen.

Ersetzen Sie den Standard-Ausnahmebehandler:

using System.Net;
using System.Net.Http;
using System.Web.Http.ExceptionHandling;
using System.Web.Http.Results;

public class HeaderAdderExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        HttpResponseMessage response = context.Request.CreateErrorResponse(
            HttpStatusCode.InternalServerError, context.Exception);
        response.Headers.Add("header", "value");

        context.Result = new ResponseMessageResult(response);
    }
}

und in Ihrem WebApi-Setup:

configuration.Services.Replace(typeof(IExceptionHandler), new HeaderAdderExceptionHandler());

Sie können nicht beide zusammen verwenden. Okay, das können Sie, aber der Handler wird niemals etwas tun, da der Filter die Ausnahme bereits in eine Antwort konvertiert hat.

Sehr wichtig zu wissen, dass wie geschrieben geschrieben wird, werden alle Ausnahmedetails an den Client gesendet. Sie möchten dies wahrscheinlich nicht in der Produktion tun. Überprüfen Sie daher alle verfügbaren Überladungen in CreateErrorResponse () und wählen Sie die für Sie passende aus.

6
Warren Rumak

Julians Antwort veranlasste mich, den Filter zu erstellen, jedoch nur mit dem Namespace System.Web (v4) und System.Web.Http (v5) (MVC-Pakete waren nicht Teil dieses bestimmten Projekts, für das dieses System verwendet wurde)

using System.Web;
using System.Web.Http.Filters;
...
public class AddCustomHeaderActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);
        actionExecutedContext.ActionContext.Response.Headers.Add("name", "value");
    }
}

Fügen Sie es der global.asax hinzu, damit es für jeden Controller/jede Aktion verwendet wird

        GlobalConfiguration.Configuration.Filters.Add(new AddCustomHeaderActionFilterAttribute());
6

Keine der beiden oben genannten Lösungen funktionierte für mich. Sie würden nicht einmal kompilieren. Hier ist was ich getan habe. Hinzugefügt: 

filters.Add(new AddCustomHeaderFilter());

zu RegisterGlobalFilters(GlobalFilterCollection filters)-Methode in FiltersConfig.cs und dann hinzugefügt

public class AddCustomHeaderFilter : ActionFilterAttribute
{
   public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
   {
       actionExecutedContext.HttpContext.Response.Headers.Add("ServerTime", DateTime.Now.ToString());
   }
}
5
julian

Je nach Anforderung dient eine einzige Codezeile für diesen Zweck.

System.Web.HttpContext.Current.Response.Headers.Add("Key", "Value")
2
Faisal Ghaffar

Dies kann vom Message-Handler problemlos durchgeführt werden. Es wird sowohl die Antwort in Ordnung als auch den Ausnahmefall behandeln.

 public class CustomHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
       // add header to request if you want
        var response = await base.SendAsync(request, cancellationToken);
        response.Headers.Add("cutomKey", "cutomValue");
        return response;
    }
}

Füge es in der Konfiguration hinzu

 config.MessageHandlers.Add(new CustomHeaderHandler());
1
pearldiver

Ich habe den normalen Pfad und den Ausnahmepfad in einer Klasse kombiniert:

public class CustomHeaderAttribute : FilterAttribute, IActionFilter, IExceptionFilter
{
    private static string HEADER_KEY   { get { return "X-CustomHeader"; } }
    private static string HEADER_VALUE { get { return "Custom header value"; } }

    public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
    {
        return (new CustomHeaderAction() as IActionFilter).ExecuteActionFilterAsync(actionContext, cancellationToken, continuation);
    }

    public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
    {
        return (new CustomHeaderException() as IExceptionFilter).ExecuteExceptionFilterAsync(actionExecutedContext, cancellationToken);
    }

    private class CustomHeaderAction: ActionFilterAttribute
    {
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (actionExecutedContext.Response != null)
            { 
                actionExecutedContext.Response.Content.Headers.Add(HEADER_KEY, HEADER_VALUE);
            }
        }
    }

    private class CustomHeaderException : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Response == null)
            {
                context.Response = context.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, context.Exception);
            }

            context.Response.Content.Headers.Add(HEADER_KEY, HEADER_VALUE);
        }
    }
}

Nichts Besonderes, aber zumindest gibt es einen Platz, um meine zusätzlichen Header zu kontrollieren. Im Moment handelt es sich nur um statischen Inhalt, aber Sie können ihn immer an eine Art Wörterbuchgenerator/-fabrik anschließen.

0
Nebula

Ich hatte das gleiche Problem, als ich versuchte, dem gesamten Controller einen neuen Header hinzuzufügen. Fügen Sie einfach "services.AddHttpContextAccessor ();" zu "startup.cs" und erstellen Sie dann Ihren Controller 

public class EnController : Controller{

        public EnController(IHttpContextAccessor myHttpAccessor)
        {

            myHttpAccessor.HttpContext.Response.Headers.Add("Content-Language", "en-US");

        }

       ... more methods here... 

}

0
Guillermo Perez