This question has been asked many times over the last few years, but all answers appear to either:
- Relate to the route not being found (in this case I refer strictly to data)
- Require use of the IHttpContextAccessor (which Microsoft docs explicitly state not to do)
- Redirecting to a resource that doesn't return the correct 404 headers (no good for SEO)
- Show a friendly error in the current component (no good for SEO and requires other functionality to be hidden in the component as a result)
- Involve a significant number of aspects/components/pages and dependency injection (very complicated for something that historically has been relatively easy, e.g. with web forms or MVC)
Within the ASP.NET Framework it was easy to return a 404 status. This could be intercepted by IIS or returned as a bespoke page. It didn't matter what level in the control/business logic hierarchy this occurred at:
Web forms
if (myThing == null) {
var ctx = HttpContext.Current;
ctx.Response.Clear();
ctx.Response.StatusCode = System.Net.HttpStatusCode.NotFound;
ctx.Response.StatusDescription = "No data was found against that URL.";
ctx.Response.End();
}
ASP.Net Framework MVC
if (myThing == null) {
ViewBag.ErrorMessage = "No data was found against that URL.";
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View("~/Views/Error/NotFound.cshtml");
}
.Net Core Razor Pages
if (myThing == null) {
return NotFound();
}
.Net Core Blazor Server Components (@page)?
Is there an equivalent within a Blazor Component (.razor file) when that component is configured to act as a @page
(not a component placed inside a .cshtml
file)?
I appreciate from the comments that the page is found and is processing the request, but to a search engine two similar URL's with different ID parameters are indexed as different pages.
A use case example would be this:
@page "/Product/{Id:int}"
@using Microsoft.EntityFrameworkCore
<h1>Product Details</h1>
@code {
[Inject]
IDbContextFactory<MyDbContext> _dbContextFactory { get; set; } = default!;
[Parameter]
public int? Id { get; set; }
protected override async Task OnInitializedAsync()
{
using var context = _dbContextFactory.CreateDbContext();
var thingToEdit = await context.MyEntities
.Where(e => e.EntityId == Id.Value)
.FirstOrDefaultAsync();
if (thingToEdit == null)
{
// Go to/show a 404 page/message, but must set HTTP status code header
}
else
{
// Show product details in this component page
}
}
}
@page
s. – Melee