0

in my _Host.cshtml I have code like this:

@{
    var theme = "main";
    if (Request.Cookies.ContainsKey("theme"))
    {
        theme = Request.Cookies["theme"];
    };
}
@theme
...
</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
...

is there way to make my theme variable value available in my blazor components ?

buga
  • 852
  • 9
  • 21

2 Answers2

2

There are two ways to pass parameters from the Server part of your Balzor Server App to the front-end part. Here's how you can do that from the _Host.cshtml file

The second way is to create a service class and add it to the DI container, and then inject an instance of the service into your Razor components. The following example decribes how you can capture the HttpContext, extract some data from the HttpContext object, initialize and instantiate the service (UserInfoService).

public void ConfigureServices(IServiceCollection services)
{
        services.AddHttpContextAccessor();

        services.AddScoped<UserInfoService>(ctx =>
        {
            var contextAccessor = ctx.GetService<IHttpContextAccessor> 
            ();
            var httpContext = contextAccessor.HttpContext;
            string userName = string.Empty;
            string email = string.Empty; ;
            bool isAuthenticated = false;

            if (httpContext.User.Identity.IsAuthenticated)
            {
                userName = httpContext.User.Identity.Name;
                email = httpContext.User.Claims.FirstOrDefault(
                                      c => c.Type == 
                                      ClaimTypes.Email)?.Value;
                isAuthenticated = 
                       httpContext.User.Identity.IsAuthenticated;
            }
            return new UserInfoService
            {
                Name = userName,
                Email = email,
                IsAuthenticated = isAuthenticated
            };
         }); 

UserInfoService.cs

 public class UserInfoService
    {
        public UserInfoService () { }
        public string Name { get; set; }
        public string Email { get; set; }
        public bool IsAuthenticated { get; set; }
    }

Usage

@page "/"

@inject UserInfoService userInfo

<div>@userInfo.Name</div>
<div>@userInfo.Email</div>
<div>@userInfo.IsAuthenticated</div>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />
enet
  • 41,195
  • 5
  • 76
  • 113
  • thnx, adding `services.AddHttpContextAccessor();` is all I actually needed, now I can use `[Inject] public IHttpContextAccessor HttpCxAccessor { get; set; }` in my components and no need to pass values from `_Host` – buga Mar 19 '22 at 20:39
  • 1
    @buga You don't want to use anything from the HttpContext in Blazor components directly as that can become null or invalid during the life of the Blazor circuit. You'll instead want to capture the values when loading _Host.cshtml (which is basically a Razor Pages page therefore loaded via an HTTP request) and then provide them back to your components from there. details: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/threat-mitigation?view=aspnetcore-6.0#blazor-and-shared-state – TheAtomicOption May 16 '22 at 18:42
1

I don't know what Theme is so I've treated it as a string.

App

<div>
@Theme
</div>
<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

@code {
    [Parameter] public string? Theme {get; set;}
}

And _host.cshtml

@page "/"
@namespace BlazorApp8.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = "_Layout";
    var theme = "Hello Blazor";
}

@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered, new { Theme =  theme}))

You can now cascade the value or add it to a service.

MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31