Search code examples
c#blazor-server-sidedotnet-httpclientnotion-api

How do I connect to my Notion API integration using .NET HttpClient? I can connect using Postman, but not my application


I can connect to my Notion page using Postman by using the call from text. I am using my internal integration. I added the Authorization and Notion-Version headers. My program is a Blazor Server App and am using Visual Studio. I am not interested in trying Python or JavaScript. This needs to be Blazor Server.

When I use my code, I get an Authorization error (401). The else clause executes. Can you help?

private async Task GetDatabaseContent()
{
    string requestUri = $"https://api.notion.com/v1/pages/{pageId}";

    client.DefaultRequestHeaders.Add(name: "Authorization", value: $"Bearer {bearerToken}");
    client.DefaultRequestHeaders.Add(name: "Notion-Version", value: "2022-06-28");

    HttpResponseMessage response = new HttpResponseMessage();

    try
    {
        response = await httpClient.GetAsync(requestUri);
    }
    catch (Exception ex)
    {
        responseMessage = $"Exception: {ex}";
    }

    if (response.IsSuccessStatusCode)
    {
        responseMessage = "Success: " + await response.Content.ReadAsStringAsync();
    }
    else
    {
        responseMessage = $"Error: {response.Content}";
        reasonPhrase = $"Error: {response.ReasonPhrase}";
    }

I've gone through countless examples from YouTube, I've looked at Pluralsight and Skillshare.


Solution

  • As in the comments...

    You have 2 instances of HttpClient, and are setting the headers, including the authorization one, on one instance - client - but sending the request using the other - httpClient.

    Each instance has its own collection of DefaultRequestHeaders, so you need to set the headers on the same instance as used to send the request.


    Note that it's usually better practice to set (most) headers per-request in a new HttpRequestMessage, which you then use with .SendAsync(), instead of e.g. .GetAsync().

    Unless you have a very simple single-threaded app, HttpClient.DefaultRequestHeaders should only have headers that are always the same for every request for the lifetime of your HttpClient, and HttpClient's lifetime would in turn usually be the lifetime of your app.

    An Authorization header typically can change - as it expires and is renewed - during the lifetime of an app, and DefaultRequestHeaders is not thread-safe:

    Headers set on this property don't need to be set on request messages again. DefaultRequestHeaders should not be modified while there are outstanding requests.

    It's even more fragile than that implies, and concurrently changing DefaultRequestHeaders from more than one thread can be problematic, as underneath it's (typically) just an array that is manipulated without any regard for thread-safety. Hence in any meaningful multi-threaded app you are creating race conditions whenever you set a DefaultRequestHeaders value.