Antonio LM
Antonio LM

Reputation: 11

How to read a cookie in razor component with RenderMode="InteractiveServer"? (Blazor Server + Net 8)

I have a Blazor Server app in Net 8.

I am trying to read a cookie with user logged data in a razor component with RenderMode="InteractiveServer" set.

This render mode, do pre-render and render (load the component two times). If I do not set the render mode it became to static and I can get the cookie data and validate user.

The problem, I need the InteractiveServer render mode to load grids and enable events in buttons.

The documentations said that use HttpContext in a static component, so I get and set the cookie in Routes.razor.

The issue is in interactive components, I loss any property or object loaded in pre-render, the HttpContext always is null.

How should I persist the information like user data that can't be erased after the full lifecycle of razor components?

Program.cs

Counter.razor

Routes.razor

I tried: Adding a scoped service to store the ClaimPrincipal (User name and role). Adding a custom AuthenticationStateProvider to store ClaimPrincipal object.

I have the same result, it has data in pre-rendering but is lost after render. So, I must be doing something wrong.

If I use the prerender flag (new InteractiveServerRenderMode(prerender:false)) it doesn't load the grids.

If I added the service as singleton, the data persist but it always be the same user and I can't have 2 different users logged at same time.

Using the context in C# class have the same result, I added in the service scoped.

`builder.Services.AddHttpContextAccessor();`

Is important mention, I get the user data from another process outside this project and only return the cookie to be consume.

Upvotes: 1

Views: 166

Answers (1)

Qiang Fu
Qiang Fu

Reputation: 8616

You could read the cookie using "javascript" or "httpcontext" depending on the rendermode. Just note that when setting to "InterActiveServer", the rendermode is SSR at fisrst, then turn to be websocket(Interactive) soon. And only when Interactive mode you could use JS interop.

@page "/"
@inject IJSRuntime js

//the script could be wrap in to js file and reference in App.razor
<script>
    function WriteCookie(name, value, days) {
        var expires;
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = "; expires=" + date.toGMTString();
        }
        else {
            expires = "";
        }
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    function ReadCookie(name) {
        console.log("test");
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
    }
</script>

@code{
    string code;
    [CascadingParameter]
    HttpContext? httpContext{ get; set; }

    protected override async Task OnInitializedAsync(){
        if (httpContext != null)
        {
            code = httpContext.Request.Cookies["MyKey"];

        }
        else
        {
            code = await js.InvokeAsync<string>("ReadCookie", "MyKey");
        }
    }
}

Upvotes: 0

Related Questions