Skip to content

Dispatch exceptions to the sync context#28936

Merged
guardrex merged 10 commits intomainfrom
guardrex/blazor-dispatch-exceptions-to-sync-context
May 8, 2023
Merged

Dispatch exceptions to the sync context#28936
guardrex merged 10 commits intomainfrom
guardrex/blazor-dispatch-exceptions-to-sync-context

Conversation

@guardrex
Copy link
Copy Markdown
Collaborator

@guardrex guardrex commented Apr 10, 2023

Fixes #28933

Notes ...

  • I felt building off of the prior example makes sense. Presumably, many readers will have just tested out the prior section's example, so they can just build on that experience to see this API in action.

    Here's what this new example builds off of ...

    https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-7.0#invoke-component-methods-externally-to-update-state

  • There's one thing in Steve's remarks that I don't understand ...

    ... the premise that you have an exception already implies you caught it. If you don't catch an external exception, then you have an unhandled exception which has nothing to do with Blazor.

    Cross-ref: [API Proposal] Allow Dispatching to Blazor Renderer Sync Context aspnetcore#46068 (comment)

    ... but error boundaries (getting them to light up here) is about trapping unhandled exceptions. The example that I have on this PR is throwing in the TimerService to show how the exception can be forwarded to the Blazor sync context.

    ... also Halter said right after that ...

    This is not something you'd want to do by default when the caller to InvokeAsync may be able to handle the exception gracefully.

    ... but again, you can do both. You can take action on it, just in the sense that you're processing it in the external code (e.g., log it), and then flow it unhandled to Blazor for the error boundary to trip on purpose. I don't see why this isn't a valid approach.

    I guess what I'm saying is that if these PU remarks are right, we don't want to show this example based on an exception in TimerService ... TimerService should handle its exceptions entirely and flow back something to the caller for processing in the Razor component on an error, not allow the unhandled exception to trip the error boundary. What I have here might be considered as an implied anti-pattern 🙈 and should be replaced with a different example.

    Besides that, is there some other or additional scenario that you'd like to show? I like this one, but I'm just pitching it as a possibility because the prior example is so good (IMO) and feeds right into the usefulness of this API AFAICT.


Internal previews

📄 File 🔗 Preview link
aspnetcore/blazor/components/index.md ASP.NET Core Razor components
aspnetcore/blazor/fundamentals/handle-errors.md aspnetcore/blazor/fundamentals/handle-errors

@guardrex guardrex marked this pull request as ready for review April 11, 2023 12:28
@guardrex guardrex requested a review from mkArtakMSFT April 11, 2023 13:06
@guardrex guardrex self-assigned this Apr 14, 2023
@guardrex guardrex requested a review from danroth27 April 19, 2023 17:52
Copy link
Copy Markdown
Contributor

@mkArtakMSFT mkArtakMSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @guardrex !

Comment thread aspnetcore/blazor/components/index.md Outdated
Comment thread aspnetcore/blazor/components/index.md Outdated
@guardrex guardrex closed this Apr 20, 2023
@guardrex guardrex reopened this Apr 20, 2023
@danroth27 danroth27 requested review from SteveSandersonMS and removed request for danroth27 April 26, 2023 15:08
Comment thread aspnetcore/blazor/components/index.md Outdated
Comment thread aspnetcore/blazor/components/index.md Outdated
Comment thread aspnetcore/blazor/components/index.md Outdated
@SteveSandersonMS
Copy link
Copy Markdown
Member

Besides that, is there some other or additional scenario that you'd like to show? I like this one, but I'm just pitching it as a possibility because the prior example is so good (IMO) and feeds right into the usefulness of this API AFAICT.

Another common scenario is if a component wants to start an async operation in a fire-and-forget way. So it's not going to await the Task, and it doesn't get back a result, but if the operation fails it wants to treat it as a lifecycle exception to put the whole component into a faulted state, or to terminate the circuit (if it's Blazor Server and there is no error boundary), and to trigger the same logging that occurs for lifecycle exceptions.

Example:

<button @onclick="SendReport">Send report</button>

@code {
    void SendReport()
    {
        // In most cases you'd want to await this task and update the UI afterwards to say the operation completed
        // But for this example, we're doing it in a fire-and-forget way, so we don't return a Task from this method
        _ = SendReportFireAndForgetAsync();
    }

    async Task SendReportFireAndForgetAsync()
    {
        try
        {
            await ReportSender.SendAsync();
        }
        catch (Exception ex)
        {
            // Because we intentionally discarded the task above, any async failures would occur off the normal
            // lifecycle call stack, and hence would not be seen by Blazor. We can treat them like lifecycle method
            // exceptions by explicitly dispatching them back to the component.
            await DispatchExceptionAsync(ex);
        }
    }
}

@guardrex
Copy link
Copy Markdown
Collaborator Author

guardrex commented May 5, 2023

Thanks @SteveSandersonMS ... I'll make these updates Monday morning and ping u back.

@guardrex
Copy link
Copy Markdown
Collaborator Author

guardrex commented May 8, 2023

@SteveSandersonMS ... Ready ...

  • We may need to work on the wording a bit more, but I dropped the "sync context" lingo.
  • Best to place it in the Handle errors article.
  • I draft it with the non-dispatching "Send Report" example first, then the dispatching example.
  • Best to put your example first, then the working demo with the timer.

Comment thread aspnetcore/blazor/fundamentals/handle-errors.md Outdated
Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
@guardrex guardrex merged commit a210fc8 into main May 8, 2023
@guardrex guardrex deleted the guardrex/blazor-dispatch-exceptions-to-sync-context branch May 8, 2023 14:12
Donciavas pushed a commit to Donciavas/AspNetCore.Docs that referenced this pull request Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dispatch exceptions to Blazor’s sync context

3 participants