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.19k stars 9.93k forks source link

[Blazor] UriHelper.NavigateTo with Parameters from a layout, requires the current page to have the same parameter #7023

Closed juanfranblanco closed 5 years ago

juanfranblanco commented 5 years ago

Describe the bug

Attempting to trigger a navigation from the Layout Page using the UriHelper.NavigateTo containing parameters will cause an error if the current page does not contain a Parameter name the same one as the navigated to.

To Reproduce

Steps to reproduce the behavior:

  1. Using Blazor latest nuget (release and preview)
  2. On the layout page, put a text box and button to trigger the navigation with a parameter using UriHelper.NavigateTo("secondPage/myparameter");
  3. Create the "secondPage" with a parameter called "myparameter".
  4. Try to navigate from your Index page, this will cause an error, "Pages.Index does not contain "myparameter".
  5. Add "myparameter" to the Index Page
  6. Now you can navigate to "secondPage/myparameter"

Expected behavior

No need to workaround adding the parameter to the current page.

AlanParr commented 5 years ago

Any idea if this one is likely to be fixed for .Net Core 3 release?

I'm hitting this with a search box in the layout that navigates to the search results page. I imagine this will be a relatively common scenario and possibly a show stopper for a lot of people.

RemiBou commented 5 years ago

I have this bug as well, you can find my layout here : https://github.com/RemiBou/Toss.Blazor/blob/pure-css-no-bootstrap/Toss.Client/Shared/Layouts/MainLayout.razor.

It seems like the rendering is called with the new url but without loading the good page component.

RemiBou commented 5 years ago

Event with the error message, the page is well displayed with the good component.

Here is the error stacktrace from the console

blazor.webassembly.js:1 WASM: Unhandled exception rendering component: blazor.webassembly.js:1 WASM: System.InvalidOperationException: Object of type 'Toss.Client.Pages.Settings.Settings' does not have a property matching the name 'tag'. blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.ParameterCollectionExtensions.ThrowForUnknownIncomingParameterName (System.Type targetType, System.String parameterName) <0x2461a38 + 0x00142> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.ParameterCollectionExtensions.SetParameterProperties (Microsoft.AspNetCore.Components.ParameterCollection& parameterCollection, System.Object target) <0x1e5e530 + 0x000e0> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync (Microsoft.AspNetCore.Components.ParameterCollection parameters) <0x1e59a80 + 0x00008> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters (Microsoft.AspNetCore.Components.ParameterCollection parameters) <0x1e597a8 + 0x000a8> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.UpdateRetainedChildComponent (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldComponentIndex, System.Int32 newComponentIndex) <0x240a650 + 0x000a8> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldFrameIndex, System.Int32 newFrameIndex) <0x2409568 + 0x00358> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldStartIndex, System.Int32 oldEndIndexExcl, System.Int32 newStartIndex, System.Int32 newEndIndexExcl) <0x1e6bc00 + 0x000ae> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldFrameIndex, System.Int32 newFrameIndex) <0x2409568 + 0x00320> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldStartIndex, System.Int32 oldEndIndexExcl, System.Int32 newStartIndex, System.Int32 newEndIndexExcl) <0x1e6bc00 + 0x000ae> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldFrameIndex, System.Int32 newFrameIndex) <0x2409568 + 0x002ac> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange (Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder+DiffContext& diffContext, System.Int32 oldStartIndex, System.Int32 oldEndIndexExcl, System.Int32 newStartIndex, System.Int32 newEndIndexExcl) <0x1e6bc00 + 0x000ae> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff (Microsoft.AspNetCore.Components.Rendering.Renderer renderer, Microsoft.AspNetCore.Components.Rendering.RenderBatchBuilder batchBuilder, System.Int32 componentId, Microsoft.AspNetCore.Components.RenderTree.ArrayRange1[T] oldTree, Microsoft.AspNetCore.Components.RenderTree.ArrayRange1[T] newTree) <0x1e6b808 + 0x0009a> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch (Microsoft.AspNetCore.Components.Rendering.RenderBatchBuilder batchBuilder, Microsoft.AspNetCore.Components.RenderFragment renderFragment) <0x1e67a20 + 0x0013a> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.Rendering.Renderer.RenderInExistingBatch (Microsoft.AspNetCore.Components.Rendering.RenderQueueEntry renderQueueEntry) <0x1e67648 + 0x00036> in :0 blazor.webassembly.js:1 WASM: at Microsoft.AspNetCore.Components.Rendering.Renderer.ProcessRenderQueue () <0x1e66f58 + 0x00056> in :0

It seems that in RenderTreeDiffBuilder line 614 newFrame.ComponentType is still equal to Index instead of Tag. I have no idea how I can debug through this source code, I can provide more information for running the project if needed.

RemiBou commented 5 years ago

I found a workaround : do the navigateto after a task.Delay.

Task.Delay(100).ContinueWith((t) => urlHelper.NavigateTo("/tag/" + addHashtagCommand.NewHashTag));
danroth27 commented 5 years ago

@RemiBou Do you have a consistent repro for this? I'm not able to reproduce this issue with the steps originally provided.

danroth27 commented 5 years ago

Here's what I tried:

With the default template (server-side or client-side, I tried both), I updated the layout to this:

@inherits LayoutComponentBase
@inject IUriHelper UriHelper

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-4">
        <a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank" class="ml-md-auto">About</a>
    </div>

    <div>
        <h2>Layout test</h2>
        <input bind="parameter" />
        <button onclick="@OnClick">Go</button>
    </div>

    <div class="content px-4">
        @Body
    </div>
</div>

@functions {
    string parameter;

    void OnClick()
    {
        UriHelper.NavigateTo($"secondPage/{parameter}");
    }
}

I then added the following SecondPage.razor:

@page "/secondPage/{myparameter}"

<h1>Second Page</h1>

<p>myparameter = @MyParameter</p>

@functions {
    [Parameter]
    string MyParameter { get; set; }
}

I ran the app and was able to navigate from home to SecondPage/foo using the text box from the layout:

image

RemiBou commented 5 years ago

The console is empty as well ? The navigation is working for me but this generates an error on the console, I just updated to the last preview I'll check if it fixes it.

danroth27 commented 5 years ago

The console looks clean too:

image

I'm going to proactively close this since it doesn't seem to reproduce anymore. But let me know if you're still seeing this issue and we'll reopen it.

pdeveau commented 5 years ago

I found a workaround : do the navigateto after a task.Delay.

Task.Delay(100).ContinueWith((t) => urlHelper.NavigateTo("/tag/" + addHashtagCommand.NewHashTag));

I'm still seeing this behavior, I'm using Remi's workaround for now, but in scenario outlined below I'll always fail.

Simplified Auth Flow

danroth27 commented 5 years ago

@pdeveau Thanks for reporting this issue! Since this issue is closed could you please open a new issue with specific steps on how to reproduce the issue you are seeing? While the sequence chart in helpful, we need to see your actual code to understand what you are doing and what's going wrong.