Добавить пользовательский заголовок для всех ответов в Web API - программирование
Подтвердить что ты не робот

Добавить пользовательский заголовок для всех ответов в Web API

Простой вопрос, и я уверен, что он имеет простой ответ, но я не могу его найти.

Я использую WebAPI, и я хотел бы отправить обратно настраиваемый заголовок для всех ответов (дата/время сервера, запрошенное разработчиком для синхронизации).

В настоящее время я пытаюсь найти ясный пример того, как в одном месте (через global.asax или в другом центральном месте) я могу получить настраиваемый заголовок для всех ответов.


Ответ принят, вот мой фильтр (почти такой же) и строка, добавленная в функцию Register конфигурации WebApi.

ПРИМЕЧАНИЕ. Материал DateTime - это NodaTime, и никакая реальная причина просто не заинтересована в его просмотре.

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

Конфигурация:

config.Filters.Add(new ServerTimeHeaderFilter());
4b9b3361

Ответ 1

Для этого вы можете использовать пользовательский ActionFilter (System.Web.Http.Filters)

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

Затем вы можете применить фильтр ко всем действиям вашего контроллера, добавив это в конфигурацию в Global.asax, например:

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

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

Ответ 2

Ни один из двух вышеперечисленных решений не работал у меня. Они даже не собирались. Вот что я сделал. Добавлено:

filters.Add(new AddCustomHeaderFilter());

to RegisterGlobalFilters(GlobalFilterCollection filters) в FiltersConfig.cs, а затем добавлен

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

Ответ 3

Джулианский ответ заставил меня создать фильтр, но только с использованием пространства имен System.Web(v4) и System.Web.Http(v5) (пакеты MVC не были частью этого конкретного проекта, в котором он использовался).

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

И добавьте его в global.asax, чтобы использовать его для каждого контроллера/действия

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

Ответ 4

Предыдущие ответы на этот вопрос не касаются того, что делать, если действие вашего контроллера вызывает исключение. Есть два основных способа заставить это работать:

Добавить фильтр исключений:

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

и в настройке WebApi:

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

Этот подход работает, потому что обработчик исключений по умолчанию WebApi отправит HttpResponseMessage, созданный в фильтре, вместо того, чтобы создавать свои собственные.

Заменить обработчик исключений по умолчанию:

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

и в настройке WebApi:

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

Вы не можете использовать оба эти метода вместе. Хорошо, ну, вы можете, но обработчик никогда ничего не сделает, потому что фильтр уже преобразовал исключение в ответ.

Самое главное отметить, что, как написано, этот код отправит все детали исключения клиенту. Вероятно, вы не хотите делать это на производстве, поэтому проверьте все доступные перегрузки на CreateErrorResponse() и выберите, какой из них подходит вашим потребностям.

Ответ 5

Согласно моему требованию, ниже одной строки кода служит цели.

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

Ответ 6

Я объединил обычный путь и исключение в одном классе:

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

Ничего необычного, но по крайней мере это дает мне одно место для контроля над моими дополнительными заголовками. Пока что это просто статический контент, но вы всегда можете подключить его к некоторому генератору словарей/ factory.

Ответ 7

У меня возникла та же проблема при попытке добавить новый заголовок ко всему контроллеру, просто добавьте "services.AddHttpContextAccessor();" в startup.cs, затем создайте свой контроллер

public class EnController : Controller{

        public EnController(IHttpContextAccessor myHttpAccessor)
        {

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

        }

       ... more methods here... 

}

Ответ 8

Это может быть легко сделано обработчиком сообщений, он будет обрабатывать как нормальный ответ, так и исключительный случай.

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

Добавьте его в конфиг

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