Home > Back-end >  Return 404 In Blazor Server Page
Return 404 In Blazor Server Page

Time:03-03

I'm trying to migrate a Razor Pages app to a Blazor Server app as part of a staged migration (rather than big bang). I'm currently moving a relatively straight forward CRUD set of pages. These pages have a typical route strucutre like...

/entity/
/entity/edit/{id}
/entity/detail/{id}
/entity/delete/{id}

In a razor page for 'edit' I would typically have an OnGetAsync method that accepts the id as a parameter, searches for the entity using the id and returns the page. However, if the id is not a valid entity my OnGet would return NotFound (IActionResult). What I'm trying to figure out is how I would do that with a Blazor Server page/component.

My blazor page looks like this (just the relevant bits)

@page "/entity/edit/{id:int}"
...
@code {
    [Parameter] public int Id { get; set; }
    public Entity Model { get; set; }
    protected override async Task OnParametersSetAsync()
    {
        Model = await SomeServiceCall.GetAsync(Id);
        if(Model == null)
            return; // TODO: Return 404 rather than the page
    }
}

How do I tell Blazor to return 404? So that my is displayed rather than my page?

CodePudding user response:

There is App.razor file in your project

<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>

Look at section, when Blazor do not find path being navigated it displays html present this section, so you can replace this line with information you want to display then

 <p role="alert">Sorry, there's nothing at this address.</p>

CodePudding user response:

This is a comment, not an answer...

Note: The Router.NotFound delegate has nothing to do with your issue. It is executed when a requested local url is not found; that is, when the url requested is outside of the SPA boundary space, as for instance, you try to navigate to a none-existent routable component in your Blazor default template. For example: "/countme." On the other hand, if you navigate to the url "/counter", the Router.Found delegate is executed.

How do I tell Blazor to return 404?

You do not...

If you retrieve your data from a Web Api end point, you can return NotFound (IActionResult) if no entity is found for a given id, and, in the code that performs the Http call, you may check the status code, and act accordingly. The following may help you:

FetchData.razor

@page "/fetchdata"
@inject IHttpClientFactory clientFactory



@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
        "https://localhost:44345/api/weatherforecast");
        request.Headers.Add("Accept", "application/json");

        var httpClient = clientFactory.CreateClient();
        var response = await httpClient.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await 
                        response.Content.ReadAsStreamAsync();
   
          forecasts = await JsonSerializer.DeserializeAsync
                     <WeatherForecast[]>(responseStream,
                     new JsonSerializerOptions { PropertyNamingPolicy = 
                                           JsonNamingPolicy.CamelCase });
       }
       else if ((int) response.StatusCode == 404)
       {
           // Navigate to the error404 razor component
            NavigationManager.NavigateTo("/error404");
        }
       else
       {
            forecasts = Array.Empty<WeatherForecast>();
        }

    } 
}

If you do not use a Web Api end point, you can create a class with a status code property... Got it ???

Note: The code above is partial, and I did not try it.

  • Related