Programing

웹 API 메시지 핸들러에서 사용자 정의 헤더 값을 추출하는 방법은 무엇입니까?

lottogame 2020. 6. 19. 19:21
반응형

웹 API 메시지 핸들러에서 사용자 정의 헤더 값을 추출하는 방법은 무엇입니까?


현재 웹 API 서비스에 다음과 같이 'SendAsync'를 재정의하는 메시지 핸들러가 있습니다.

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
  //implementation
}

이 코드 내에서라는 사용자 정의 추가 요청 헤더 값을 검사해야합니다 MyCustomID. 문제는 내가 다음을 할 때입니다.

if (request.Headers.Contains("MyCustomID"))  //OK
    var id = request.Headers["MyCustomID"];  //build error - not OK

... 다음과 같은 오류 메시지가 나타납니다.

'System.Net.Http.Headers.HttpRequestHeaders'유형의 표현식에 []를 사용하여 인덱싱을 적용 할 수 없습니다.

이 재정의 된 메서드에 전달 된 ( MSDN Documentation ) 인스턴스 를 통해 단일 사용자 지정 요청 헤더에 액세스하려면 어떻게 해야합니까?HttpRequestMessage


다음과 같이 해보십시오 :

IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");
var id = headerValues.FirstOrDefault();

헤더에 대한 액세스 권한이 항상 보장되지 않는 경우 사용할 수있는 헤더에 TryGetValues ​​메소드도 있습니다.


throws exception키가없는 경우 아래 줄 입니다.

IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");

해결 방법 :

System.Linq 포함;

IEnumerable<string> headerValues;
var userId = string.Empty;

     if (request.Headers.TryGetValues("MyCustomID", out headerValues))
     {
         userId = headerValues.FirstOrDefault();
     }           

Youssef의 답변을 확장하기 위해 단위 테스트 중에이 상황이 발생했기 때문에 헤더가 존재하지 않는 Drew의 우려 사항을 기반 으로이 방법을 작성했습니다.

private T GetFirstHeaderValueOrDefault<T>(string headerKey, 
   Func<HttpRequestMessage, string> defaultValue, 
   Func<string,T> valueTransform)
    {
        IEnumerable<string> headerValues;
        HttpRequestMessage message = Request ?? new HttpRequestMessage();
        if (!message.Headers.TryGetValues(headerKey, out headerValues))
            return valueTransform(defaultValue(message));
        string firstHeaderValue = headerValues.FirstOrDefault() ?? defaultValue(message);
        return valueTransform(firstHeaderValue);
    }

사용법 예는 다음과 같습니다.

GetFirstHeaderValueOrDefault("X-MyGuid", h => Guid.NewGuid().ToString(), Guid.Parse);

또한 더 일반적인 솔루션에 대한 @ doguhan-uluca의 답변을 살펴보십시오.


HttpRequestMessage에서 여러 키 값에 액세스해야 할 때마다 ' 개별 HTTP 헤더 값을 리턴합니다 '라는 새 메소드를 작성하고 키 값으로이 메소드를 호출하십시오.

public static string GetHeader(this HttpRequestMessage request, string key)
        {
            IEnumerable<string> keys = null;
            if (!request.Headers.TryGetValues(key, out keys))
                return null;

            return keys.First();
        }

@neontapir의 솔루션을 더욱 확장하기 위해 HttpRequestMessage 또는 HttpResponseMessage에 동일하게 적용 할 수 있고 손으로 코딩 된 표현식 또는 함수가 필요하지 않은보다 일반적인 솔루션이 있습니다.

using System.Net.Http;
using System.Collections.Generic;
using System.Linq;

public static class HttpResponseMessageExtensions
{
    public static T GetFirstHeaderValueOrDefault<T>(
        this HttpResponseMessage response,
        string headerKey)
    {
        var toReturn = default(T);

        IEnumerable<string> headerValues;

        if (response.Content.Headers.TryGetValues(headerKey, out headerValues))
        {
            var valueString = headerValues.FirstOrDefault();
            if (valueString != null)
            {
                return (T)Convert.ChangeType(valueString, typeof(T));
            }
        }

        return toReturn;
    }
}

샘플 사용법 :

var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue");

For ASP.Net Core there is an easy solution if want to use the param directly in the controller method: Use the [FromHeader] annotation.

        public JsonResult SendAsync([FromHeader] string myParam)
        {
        if(myParam == null)  //Param not set in request header
        {
           return null;
        }
        return doSomething();
    }   

Additional Info: In my case the "myParam" had to be a string, int was always 0.


For ASP.NET you can get the header directly from parameter in controller method using this simple library/package. It provides a [FromHeader] attribute just like you have in ASP.NET Core :). For example:

    ...
    using RazHeaderAttribute.Attributes;

    [Route("api/{controller}")]
    public class RandomController : ApiController 
    {
        ...
        // GET api/random
        [HttpGet]
        public IEnumerable<string> Get([FromHeader("pages")] int page, [FromHeader] string rows)
        {
            // Print in the debug window to be sure our bound stuff are passed :)
            Debug.WriteLine($"Rows {rows}, Page {page}");
            ...
        }
    }

request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault()

modern variant :)


One line solution

var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();

참고URL : https://stackoverflow.com/questions/14967457/how-to-extract-custom-header-value-in-web-api-message-handler

반응형