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.