Search code examples
blazorhttp-postblazor-server-side.net-7.0

Blazor: Injected service data are fine during prerender but disappears during second load


I'm running component rendering as ServerPrerender. Using .Net 7. I've put my HTTP Post data into scoped service that I'm injecting into a Razor component. During prerender the data is read fine from this service but when the OnInitializedAsync is called again the values from the service are null.

If I change the component rendring to Server the values are always null.

I've searched this site but been unable to solve this.

I've got a Form in a page that does a POST to a Razor component page that should read the values and get data based on them.

Edit1: My code is based on the answer here: How to use Form data received from a POST request in Blazor pages?

I've a _Host.cshtml that has a Model where I'm reading the form data in OnPostAsync into a scoped service. This service is then injected into my .razor component where I'm trying to read the data within.

Edit 2: _Host.cshtml

@model HostPageModel
<component type="typeof(App)" render-mode="ServerPrerendered" />
or
<component type="typeof(App)" render-mode="Server" />

HostPageModel

// postFormService is injected by the DI
public HostPageModel(PostFormService postFormService)
{
    PostFormService = postFormService;
}

private PostFormService PostFormService { get; }

public async Task OnPostAsync()
{
    // store the post form in the PostFormService
    PostFormService.Form = Request.Form;
}

MyRazor.razor

@inject PostFormService PostFormService
@code {
  var loginUserId = PostFormService.Form?["LoginUserId"];
}

Edit 3: I've also tried this approach but haven't been able to get any data passed to my Razor component. _Host.csthml (The Model.FormGuid is being set by OnPost of the model)

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

App.razor (The Guid gets printed fine)

<div>@this.FormGuid</div>
<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <h3>Not authorized</h3>
                    <Saga.Presentation.Web.Core.Pages.RedirectToLogin />
                </NotAuthorized>
                <Authorizing>
                    <p>Logging in...</p>
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Page not found.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

@code{
    [Parameter] 
    public Guid FormGuid { get; set; }

    protected override void OnInitialized()
    => this.FormDataService.GetFormData(FormGuid);
}

Component.razor (The FormGuid is null here)

@code {
    [CascadingParameter] public Guid FormGuid { get; set; }
}

Solution

  • So I got this to work by following what the question author did here: Blazor Server: Issue with scoped service

    In short

    1. Add a property to my Data Service called FormData which holds the data to be used in the Razor pages.
    2. I create the data object in the Model class of the _Hosts.cshtml file. In my case I'm reading HTTP POST data so I've got a OnPostAsync() method where I'm reading the values from Request.Form.
    3. I pass that object to App.razor by adding "param-FormData" to the component render

    < component type="typeof(App)" render-mode="Server" param-FormData="@Model.FormData" >

    1. Created the FormData property in App.razor with the [Parameter] attribute
      [Parameter]
      public FormData FormData { get; set; } = new();

    2. In OnIntialized in App.razor I set the data property of the injected service

      FormDataService.AddFormData(FormData);

    Now I can inject the service into any other Razor component and get the values.

    @inject FormDataService FormDataService