Blazor and HttpContext

HttpContext is an object that is accessible from any Razor page or middleware (by way of IHttpContextAccessor) inside of an Asp.Net Core application. This object can be used to access information about the current http session, such as the currently logged in user, session data, the request object, the http connection itself and more.

So does that mean his object can also be accessed inside Blazor code? Well, technically yes. There is nothing preventing you from doing so. If you try to access the context from a Blazor page, your code will compile and run merrily, all the way until you try to access the data in context, at which point you will run into a wall of null reference exceptions. We believe making the HttpContext accessible from a Blazor page was an oversight on Microsoft's party, but surely there is a technical reason why it is there. Perhaps it has to do with the fact that a Blazor page is really a Razor page under the hood. But who knows. The point is, don't use it!

What to do?

In case you need certain information from the context, there are a number of ways you can get that information. One is by writing javascript functions that return that information and then using IJsInterop to call said functions and get the data. This works, because the client side will likely have the information you are looking for (such as cookies). But this method is very clunky. First of all, the whole point of using Blazor is so that you never have to write javascript ever again!

A better way is to take advantage of the fact that all Blazor apps have one purely Razor page, which is the _Host.cshtml file. It is perfectly safe to access the context from here, so let's see how we can use that to our advantage.

Passing Parameters into the App

The first thing you do is open up _Host.cshtml and find the following (or the equivalent flavor you are using):

<app>
    @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>

All that is doing is telling Razor to render the html of the App component, which is our Blazor application class. We need a way to pass the relevant information from the context into the App component.

@(await Html.RenderComponentAsync<App>(
    RenderMode.ServerPrerendered, 
    new {
        Cookies = string.Join(";", HttpContext.Request.Cookies.Select(c => $"{c.Key}={c.Value}")), 
        UserId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)
    }))

The RenderComponentAsync method has an override that accepts an object parameter. In this example we are simply passing an anonymous object with the information we need, which is the request cookies and the currently logged in user's id.

So how does the App component able to access this information? By way of parameters. Inside the @code block of your App.razor file, add the following properties:

[Parameter]
public string Cookies { get; set; }

[Parameter]
public string UserId { get; set; }

And that's it, this data has now been propagated into the Blazor world. Note that the name of the properties must match the names you used in the anonymous object in the previous step. That's great, but how do I get this to my pages? There are a number of ways, the first one being by way of cascading parameters. However, this will end up being clunky if you have a lot of parameters.

A better way is to use a scoped service to store this information and then inject this service into any page or component that needs the cookie or user id. This service can look like the following:

public class AppStateService
{
    public string Cookies { get; set; }

    public string UserId { get; set; }
}

Then, in Startup.cs do the following: services.AddScoped<AppStateService>();. This will make the service scoped, which means it lives until the Blazor circuit is disconnected (usually when the user closes the tab or refreshes the page).

And finally in App.razor, do this:

@inject AppStateService AppState
...
@code {
    protected override void OnInitialized()
    {
        AppState.Cookies = Cookies;
        AppState.UserId = UserId;

        base.OnInitialized();
    }
}

This works, because the App component runs before any of your other pages, so by the time those are loaded, the AppStateService's data will be populated.

Table of Contents

  • Refit and Controllers

    We talk about how to create apis alongside your Blazor app and how to access those apis using Refit.

  • Blazor Gotchas

    This article explores various Blazor pitfalls that you should be aware of.

  • Blazor and HttpContext

    Here we discuss how to correctly use HttpContext in a Blazor app.

  • SignInManager and Blazor

    Blazor and SignInManager don't play well together. Let's see how to get around that.

  • One Year with Blazor

    We've switched over to using Blazor exclusively a year ago. Here are our thoughts.



An error has occurred. This application may no longer respond until reloaded. Reload 🗙