VisualReCode / Cocoon

An implementation of the Strangler Fig pattern for ASP.NET Core
Apache License 2.0
62 stars 10 forks source link

Wrong routing when component implements class based on ComponentBase #29

Open dzambo2302 opened 2 years ago

dzambo2302 commented 2 years ago

Hello! I'm trying to rewrite a legacy webforms app using Blazor server. However, I'm having some problems with proxy routing.

Let's imagine ComponentBase class implementation such as this one:

public class CancellableComponent : ComponentBase, IDisposable
{
    internal CancellationTokenSource _cts = new();

    public void Dispose()
    {
        _cts.Cancel();
        _cts.Dispose();
    }
}

and the component that is implementing it

@page "/Settings"
@implements CancellableComponent
...

Then routing is strange, when I hit URL (for example https://localhost:5001/Settings) directly, it is not routed to Blazor page, but to the original webforms page. But when I click on its tab in the menu (Blazor part) it is routed correctly. Of course, when I remove @implements CancellableComponent from Blazor page, routing is correct in any circumstances.

How should I approach this situation, is there any chance of implementing my custom component base and having correct routing? Many thanks

dzambo2302 commented 2 years ago

I guess that possible solution to my problem coud be change of routing discovery to something like this:

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.Components;

namespace ReCode.Cocoon.Proxy.Proxy
{
    public static class BlazorRouteDiscovery
    {
        public static IEnumerable<string> FindRoutes(Type type)
        {
            var assembly = type.Assembly;
            foreach (var exportedType in assembly.GetExportedTypes().Where(t => t.IsSubclassOf(typeof(ComponentBase)))
            .Where(c => c.GetCustomAttributes(inherit: true).OfType<RouteAttribute>().Any()))
            {
                    var routeAttribute = exportedType.GetCustomAttribute(typeof(RouteAttribute)) as RouteAttribute;
                    if (routeAttribute is null) continue;
                    yield return routeAttribute.Template;
            }
        }
    }
}