dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.44k stars 10.02k forks source link

Blazor doesn't render ErrorBoundary's ErrorContent when there are two different exceptions inside it's ChildContent #39814

Open xiety opened 2 years ago

xiety commented 2 years ago

Is there an existing issue for this?

Describe the bug

ErrorBoundary renders nothing when there are two different errors inside it's ChildContent.

Expected Behavior

ErrorBoundary renders exception information.

Steps To Reproduce

App.razor

<ErrorBoundary>
    <ChildContent>
        <ComponentWithError />
    </ChildContent>
    <ErrorContent>
        <div style="background: red">@context</div>
    </ErrorContent>
</ErrorBoundary>

ComponentWithError.razor

@{
    throw new Exception("error2");
}

@code
{
    protected override async Task OnInitializedAsync()
    {
        throw new Exception("error");
    }
}

Exceptions (if any)

No response

.NET Version

6.0.101

Anything else?

I originally ran into this problem when I misspelled the parameter name in the inner component of ComponentWithError: <ComponentWithoutProp BadProp=1 /> Which throws an exception by itself.

Also with exception inside void OnInitialized() everything works fine.

ghost commented 2 years ago

Thanks for contacting us. We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

TanayParikh commented 2 years ago

Hey @xiety, thanks for reaching out.

I just tried this out and was unable to reproduce this issue. Can you please provide a minimal, public, GitHub repository which reproduces this issue?

image
ghost commented 2 years ago

Hi @xiety. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

xiety commented 2 years ago

Hi @TanayParikh. You removed async from my method and the problem is gone.

I reproduced it by adding async back: https://blazorrepl.telerik.com/cQPuQTml54XlfWdS53

TanayParikh commented 2 years ago

Hmm interesting. I did that to avoid CS1998, however it's interesting that removing the async keyword results in an actual change in behavior.

image

Generally, if you aren't awaiting anything, you don't need to provide the async keyword (and can just return Task.CompletedTask).

xiety commented 2 years ago

I tried to make a minimal reproducible example. Of course there is much more code to await in real use case.

TanayParikh commented 2 years ago

So the async isn't the issue per-say, it's the missing await if you have async. The following works as expected:

https://blazorrepl.telerik.com/GQFuGAFq46B8euzE23

xiety commented 2 years ago

And the following does not work:

    protected override async Task OnInitializedAsync()
    {
        await File.ReadAllTextAsync("NOT EXISTS");
    }

https://blazorrepl.telerik.com/mcbucUvh06LNyOkj40

AMUCOMO commented 1 year ago

I can confirm the bug. It is especially painful in the following setup: Say you have multiple different components, that all react to the same data (lets say a injected service). When the data-state is bad, I throw on purpose in each component, at the beginning of BuildRenderTree, so I actually can KNOW what went wrong (checking for the state of data). But ofc this is all in vain, if the ErrorBoundary cannot handle multiple exceptions at the same time during one "render cycle".

AMUCOMO commented 1 year ago

Here is my example:

//parent.razor
@page "/errb1"
@using System.Diagnostics
@layout BaseLayout
@{
    Debug.WriteLine($"> * * *BRT * * * {NAME}");
}
<div style="background-color: black; color: yellow">
    <h1>@NAME</h1>
    <h4>string: @_s</h4>
</div>
<button @onclick=Click>Click</button>

<ChildA MyParam1=@_s></ChildA>
<ChildB MyParam1=@_s></ChildB>

@code {
    const string NAME = "Parent";
    string _s = "unset";

    void Click()
    {
        _s = null;
    }
}
//ChildA and ChildB
@using System.Diagnostics
@{
    Debug.WriteLine($"> * * *BRT * * * {NAME}");
}
<div style="background-color: purple; color: cyan">
    <h1>@NAME</h1>
    <h4>string: @MyParam1</h4>
    @{
        var x = MyParam1.Length; //this will throw the NullReferenceException, comment this out in ONE Child -> ErrorBoundary works, but if its enabled in both, it won't work!!!
    }
</div>
@code {
    const string NAME = "AAA"; //BBB for CHildB

    [Parameter]
    public string? MyParam1 { get; set; } = "unset";
}
//BaseLayout
@inherits LayoutComponentBase
<ErrorBoundary>
    <ChildContent>
    </ChildContent>
    <ErrorContent>
              WONT DISPLAY HERE!!!
    </ErrorContent>
</ErrorBoundary>
ghost commented 1 year ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

guardrex commented 1 year ago

btw - This appears to be a duplicate of https://github.com/dotnet/aspnetcore/issues/38905.

tjs37 commented 1 year ago

If you remove comment from second InputText control (multiple errors), ErrorContent shows nothing

index.razor

@page "/"

<ErrorBoundary>
    <ChildContent>
        <Component2>
            <InputText @bind-Value="@test.Prop1"></InputText>
        </Component2>
        <Component2>
            @* <InputText @bind-Value="@test.Prop2"></InputText> *@
            @* if you uncomment above line ErrorContent shows nothing *@
        </Component2>
    </ChildContent>
    <ErrorContent Context="ex">
        <p>@ex.Message</p>
        <p>@ex.StackTrace</p>
    </ErrorContent>
</ErrorBoundary>

@code {
    Test test;
    class Test
    {
        public string? Prop1 { get; set; }
        public string? Prop2 { get; set; }
    }
}

Component2.razor

<div>
    @ChildContent
</div>

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
}
ghost commented 1 year ago

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

stephajn commented 10 months ago

I'd like this to get some more attention than just pushing it back from one year to the next. This has been around since .NET 6, and now you have three releases with this same issue.

I can confirm that this is an issue for me as well. The ErrorBoundary should be catching and rendering its ErrorContent if some async work in OnInitializedAsync throws shouldn't it? Instead it bubbles up to the whole application, whereas I want it to do what it claims to do. Keep it within the component's ErrorBoundary and handle it there.

ghost commented 10 months ago

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.