program story

Web API의 모든 응답에 사용자 지정 헤더 추가

inputbox 2021. 1. 11. 08:07
반응형

Web API의 모든 응답에 사용자 지정 헤더 추가


간단한 질문입니다. 답은 간단하지만 찾을 수 없습니다.

WebAPI를 사용하고 있으며 모든 응답 (동기화를 위해 개발자가 요청한 서버 날짜 / 시간)에 사용자 지정 헤더를 다시 보내고 싶습니다.

현재 한 곳에서 (global.asax 또는 다른 중앙 위치를 통해) 모든 응답에 대해 표시 할 사용자 지정 헤더를 가져올 수있는 방법에 대한 명확한 예를 찾기 위해 고군분투하고 있습니다.


대답이 허용됩니다. 여기에 내 필터 (거의 동일)와 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());

이를 위해 사용자 정의 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());

글로벌 구성 라인없이 원하는 작업에 필터 속성을 적용 할 수도 있습니다.


Julian의 대답으로 인해 필터를 만들어야하지만 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());

이 질문에 대한 이전 답변은 컨트롤러 작업에서 예외가 발생하는 경우 수행 할 작업을 다루지 않습니다. 작동하도록하는 두 가지 기본 방법이 있습니다.

예외 필터 추가 :

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 ()에서 사용 가능한 모든 오버로드를 확인하고 필요에 맞는 것을 선택하십시오.


위의 두 가지 솔루션 중 어느 것도 저에게 효과적이지 않았습니다. 그들은 심지어 컴파일하지도 않을 것입니다. 내가 한 일입니다. 추가 :

filters.Add(new AddCustomHeaderFilter());

RegisterGlobalFilters(GlobalFilterCollection filters)FiltersConfig.cs의 방법 및 첨가

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

According to my requirement, below single line of code serves the purpose.

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

It can be done by the messagehandler easily, it will handle both ok response and exception case.

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

Add it in the config

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

I combined the normal and exception path in one class:

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

Nothing fancy but at least it gives me one place to control my additional headers. For now it's just static content but you could always hook it up to some sort of dictionary generator/factory.


I had the same problem while trying to add a new header to the whole controller, just add "services.AddHttpContextAccessor();" to startup.cs then create your controller

public class EnController : Controller{

        public EnController(IHttpContextAccessor myHttpAccessor)
        {

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

        }

       ... more methods here... 

}

ReferenceURL : https://stackoverflow.com/questions/20349447/add-custom-header-to-all-responses-in-web-api

반응형