Skip to content

[Pre4] Final round of Blazor content/WN updates #35433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 13, 2025

Conversation

@guardrex guardrex requested a review from ilonatommy May 13, 2025 11:35
@guardrex
Copy link
Collaborator Author

@ilonatommy ... The Not Found content is on this wrap-up PR. One question comes to mind ...

For the OnNotFound scenario, can we do anything inside of OnNotFound here with the sender or args? I tried casting args to NotFoundEventArgs, but there doesn't seem to be anything interesting that can be done with it.

@guardrex
Copy link
Collaborator Author

@ilonatommy ... We've hit release, so I'm going to go ahead with this. You can let me know here if you have update requests. Also, there's that one question that I asked in the last comment.

@guardrex guardrex merged commit 1f77e03 into main May 13, 2025
3 checks passed
@guardrex guardrex deleted the guardrex/blazor-preview4-final-updates branch May 13, 2025 18:07
mccoylstevens pushed a commit to POWER-OF-ATTORNEY/AspNetCore.Docs that referenced this pull request May 13, 2025
@ilonatommy
Copy link
Member

ilonatommy commented May 14, 2025

For the OnNotFound scenario, can we do anything inside of OnNotFound here with the sender or args?

No, they are left there for possible future use, currently they do not play any role.

Sorry for the delay, I will review now and post comments.

Edit: I read it and I have no comments, everything looks awesome. Out of curiosity, why do we copy-paste the same content to aspnetcore/release-notes/aspnetcore-10/includes/blazor.md and aspnetcore/blazor/fundamentals/routing.md? Cross-linking these sections would not look good?

@guardrex
Copy link
Collaborator Author

It depends on the coverage. If the new feature coverage is somewhat short, I'll often place a copy into both places and not bother with a cross-link. If the coverage is long and/or has long examples, I tend to place a general description into the What's New article and cross-link to the reference article content. If you ever feel that the What's New article should have more or less coverage for a feature, let me know 👂. I can move coverage one way or the other. If the coverage is different, I always place a cross-link.

WRT OnNotFound, Dan told me last night in a message that it might be more useful for developers working on custom routers. We could say more about why it's there, and we could improve the example to make it actually do something valuable ... an actual use case that makes sense. I'm 👂 on if we can improve that bit of the coverage.

@guardrex
Copy link
Collaborator Author

... and Dan said something that we should probably place for OnNotFound ...

We should just be clear that the event is only fired when NavigationManager.NotFound is called, and not for any 404 response.

I'll keep that in mind for a patch PR today after I hear back from you.

@ilonatommy
Copy link
Member

WRT OnNotFound, Dan told me last night in a message that it might be more useful for developers working on custom routers. We could say more about why it's there, and we could improve the example to make it actually do something valuable ... an actual use case that makes sense. I'm 👂 on if we can improve that bit of the coverage.

I believe the use cases for custom router would be (I have not tested any of these):

  • A/B testing:
public class ExperimentRouter : ComponentBase
{
    [Inject] private NavigationManager NavigationManager { get; set; }
    [Inject] private IExperimentService ExperimentService { get; set; }
    
    protected override void OnInitialized()
    {
        var uri = NavigationManager.Uri;        
        if (uri.Contains("/new-feature") && !ExperimentService.IsInExperimentGroup("new-feature-test"))
        {
            // Users not in test group get 404 - feature doesn't exist for them
            NavigationManager.NotFound();
        }
    }
}
  • dynamic route validation e.g.
if (!IsValidRoute(requestedPath))
{
    NavigationManager.NotFound();
    return;
}
  • Internationalized routing, when url with requested locale doesn't exist:
if (!supportedLocales.Contains(requestedLocale))
{
    NavigationManager.NotFound();
}

@guardrex
Copy link
Collaborator Author

I see, but those use cases are going to result in Not Found being triggered. I'm not clear on what custom code would be placed into the OnNotFound event for those or other scenarios that would do something useful.

@ilonatommy
Copy link
Member

ilonatommy commented May 14, 2025

I see, but those use cases are going to result in Not Found being triggered. I'm not clear on what custom code would be placed into the OnNotFound event for those or other scenarios that would do something useful.

Right. Then beyond logging for diagnostic or telemetry I can see only a possibility of passing the data to NotfoundPage.razor via a service. When we want to display custom content, e.g. "Movie was not found" when NotFound was called on Movie.razor and "User was not found" when called on User.razor. We can call a service that will change the context of the message. CThe community asked about it yesterday but back then, it did not cross my mind. Let me cover it in short snippets

// Router.razor

@inject NotFoundContextService NotFoundContext

<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
        <FocusOnNavigate RouteData="routeData" Selector="h1" />
    </Found>
    <NotFound>
        <LayoutView Layout="typeof(Layout.MainLayout)">
            <h1>@(NotFoundContext.Context) Not Found</h1> 
            <h3>DynamicNotFoundPage</h3>
            <div>
                <p>@(NotFoundContext.CustomMessage ?? "Sorry, the page you requested could not be found")</p>
                </div>
        </LayoutView>
    </NotFound>
</Router>

// Movie.razor

@inject MovieService MovieService
@inject NavigationManager NavigationManager
@inject NotFoundContextService NotFoundContext

protected override async Task OnInitializedAsync()
    {
        NavigationManager.OnNotFound += HandleNotFound;
        movie = await MovieService.GetMovieByIdAsync(id);

        if (movie == null)
        {
            NavigationManager.NotFound();
        }
    }

    private void HandleNotFound(object? sender, NotFoundEventArgs e)
    {
        NotFoundContext.UpdateContext("Movie", "The requested movie was not found");
    }

    public void Dispose()
    {
        NavigationManager.OnNotFound -= HandleNotFound;
    }

// User.razor


    protected override async Task OnInitializedAsync()
    {
        NavigationManager.OnNotFound += HandleNotFound;
        movie = await UserService.GetUserByIdAsync(id);

        if (movie == null)
        {
            NavigationManager.NotFound();
        }
    }

    private void HandleNotFound(object? sender, NotFoundEventArgs e)
    {
        NotFoundContext.UpdateContext("User", "The requested user was not found");
    }

    public void Dispose()
    {
        NavigationManager.OnNotFound -= HandleNotFound;
    }

// NotFoundContextService.cs

    public class NotFoundContextService
    {
        public string Context { get; private set; } = "General";
        public string CustomMessage { get; private set; } = "The requested resource was not found";

        public void UpdateContext(string context, string customMessage)
        {
            Context = context;
            CustomMessage = customMessage;
        }
    }

@guardrex
Copy link
Collaborator Author

guardrex commented May 14, 2025

Fantastic! 🎉 ... I'll place that on a PR this afternoon and ping you on it for review.

UPDATE: It will be tomorrow (Thursday). I got bogged down in other work today ⛰️⛏️😅.

@ilonatommy
Copy link
Member

I don't remember where but you asked somewhere if OnNotFound event gets fired when we just set HttpContextAccessor.HttpContext.Response.StatusCode = 404 without calling navigationManager.NotFound(). I just double checked and it's not triggered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants