In a server-side Blazor application (Core 3.1) have a Razor that accepts an identifier in the @page
attribute. If the identifier supplied in the URL corresponds to an existing entity, the page will render fine. However, if the identifier is not a known entity (as determined by its presence in the repository) I would like the system to perform whatever action corresponds to 404 Not Found. I don't know this, however, until the route has already been matched and my page's OnInitialized()
is executing.
How can I "redirect" to the default 404 handling in this case.
The page looks like this:
@page "/{projectname}"
<!-- HTML Here -->
@code {
[Parameter]
public string ProjectName {get; set;}
private UpdateProjectViewModel Project;
protected override void OnInitialized()
{
var project = Repository.Get(ProjectName);
if (project == null)
{
WANT TO USE 404 ROUTING HERE.
}
Project = new UpdateProjectViewModel(project));
}
}
In case you want to "remain" on the same route while showing error 404:
Create a class NotFoundListener.cs
public class NotFoundListener
{
public Action OnNotFound { get;set; }
public void NotifyNotFound()
{
if(NotifyNotFound != null)
{
OnNotFound.Invoke();
}
}
}
Inject it as a scoped service
builder.Services.AddScoped<NotFoundListener>();
In your MainLayout.razor
@inherits LayoutComponentBase
@inject NotFoundListener nfl;
<PageTitle>ImportTesting</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@if (notFound)
{
<h1>Could not find the content you are looking for</h1>
}else
{
@Body
}
</article>
</main>
</div>
@code{
private bool notFound;
protected override void OnInitialized() => nfl.OnNotFound += SetNotFound;
void SetNotFound()
{
notFound = true;
StateHasChanged();
}
}
And in the page you want to raise 404:
protected override void OnInitialized()
{
if (project == null)
{
nfl.NotifyNotFound();
}
}
This will:
Now,
In case you want to re-use your standard error page:
You error page is defined in your App.razor
<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>
You can create your own NotFoundComponent.razor
component
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
Your updated App.razor
looks like this:
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<NotFoundComponent/>
</NotFound>
</Router>
And then you can create a page that simply refers to the same component
NotFoundPage.razor
@page "/NotFound"
<NotFoundComponent />
And then use your page redirection as below
From your OnInitialized()
@page "/{projectname}"
<!-- HTML Here -->
@code {
[Parameter]
public string ProjectName {get; set;}
private UpdateProjectViewModel Project;
protected override void OnInitialized()
{
var project = Repository.Get(ProjectName);
if (project == null)
{
NavigationManager.NavigateTo("/NotFound");
}
Project = new UpdateProjectViewModel(project));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With