Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read specific HTTP header value from key/value collection in C#

Tags:

c#

I'm trying to read two header values from an HTTP method and have a few gaps in my C# knowledge. I can see a Results View in the locals when debugging and I can also see it is a System.Collections.Generic but I don't know how to access this list to obtain my two values.

Here is my Azure Function App code:

[FunctionName("Tenant")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Tenant/{DomainName}")]HttpRequestMessage req, string DomainName, [Inject(typeof(ITableOps))]ITableOps _tableOps, TraceWriter log)
{
    var headers = req.Headers;
    var settings = _tableOps.GetTenantSettingsAsync(DomainName);
    return req.CreateResponse(HttpStatusCode.OK, settings.Result);
}

Results View

From this key/value list I'd like to get the key named apikey and domainName and I've tried all sorts of strange ways to do this:

 headers.ToList()[0]

or

var key = headers.Where(x => x.Key == "apikey")

Given the second example, key ends up being another list:

List

I've seen quite a few examples on using foreach loops but in my case I thought I could use a lambda to extract the value since I'm expecting two very specific key names. I realize this is easy to obtain but I'm at a loss on how to proceed.

like image 274
Jason Shave Avatar asked Oct 28 '25 00:10

Jason Shave


2 Answers

Headers is a HttpRequestHeaders class, that class has a TryGetValues function that is for this exact situation.

[FunctionName("Tenant")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Tenant/{DomainName}")]HttpRequestMessage req, string DomainName, [Inject(typeof(ITableOps))]ITableOps _tableOps, TraceWriter log)
{
    var headers = req.Headers;
    if(!headers.TryGetValues("apiKey", out var apiKeys) ||
       !headers.TryGetValues("domain", out var domains))
    {
        return req.CreateResponse(HttpStatusCode.Forbidden);
    }
    var apiKey = apiKeys.First();
    var domain = domains.First();

    //Do something with apiKey and domain here.

    var settings = _tableOps.GetTenantSettingsAsync(DomainName);
    return req.CreateResponse(HttpStatusCode.OK, settings.Result);
}

There also is a GetValues function that could be used like

[FunctionName("Tenant")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "Tenant/{DomainName}")]HttpRequestMessage req, string DomainName, [Inject(typeof(ITableOps))]ITableOps _tableOps, TraceWriter log)
{
    var headers = req.Headers;
    var apiKey = headers.GetValues("apiKey").First();
    var domain = headers.GetValues("domain").First();

    //Do something with apiKey and domain here.

    var settings = _tableOps.GetTenantSettingsAsync(DomainName);
    return req.CreateResponse(HttpStatusCode.OK, settings.Result);
}

However GetValues will throw a InvalidOperationException if the header was not sent with the request so doing a TryGetValues would be faster due to no exception overhead.

The HttpRequestHeaders is a kind of like a Dictionary<string, List<string> internally so a dictionary lookup would be the preferred way to do it.

like image 177
Scott Chamberlain Avatar answered Oct 30 '25 16:10

Scott Chamberlain


One option is to get one item at the time is to use FirstOrDefault() which returns the first element from the list that matches your expression. If no elements exist it will return null.

var key = headers.FirstOrDefault(x => x.Key == "apikey");

To get both keys

var yourKeys = new List<string>{"apikey", "domainName"};
headers.Where(x => yourKeys.Contains(x.Key)).ToList();
like image 26
Marcus Höglund Avatar answered Oct 30 '25 15:10

Marcus Höglund



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!