Open Closed

Using Azure SignalR backplane for abp Blazor app #2054


User avatar
0
ysemykin created

Hi, we need to run abp server blazor app in azure accross multi node app service plan so we tried to use Azure SignalR service as Blazor app backplane. We don't have any requirements for SignalR hub hosting in our app from functional point of view (like chat app or similar).

We are getting an exception below when we run the app while Blazor stock app worked just fine with the same configuration. Also, I noticed that based on attached image that the app originally opens the connection to Azure SignalR service but then still tried to connect to local SignalR hub and then fails.

If you're creating a bug/problem report, please include followings:

  • ABP Framework version: v4.4.2
  • UI type: Blazor
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace: [20:51:42 INF] HTTP POST /_blazor/negotiate?negotiateVersion=1 responded 200 in 2.0234 ms [20:51:44 WRN] Unhandled exception rendering component: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown. Volo.Abp.Authorization.AbpAuthorizationException: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown. at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.CheckAsync(IAuthorizationService authorizationService, AuthorizationPolicy policy) at Volo.Abp.Authorization.MethodInvocationAuthorizationService.CheckAsync(MethodInvocationAuthorizationContext context) at Volo.Abp.Authorization.AuthorizationInterceptor.AuthorizeAsync(IAbpMethodInvocation invocation) at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Features.FeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Volo.Abp.AuditLogging.Blazor.Pages.AuditLogging.AuditLogs.GetEntitiesAsync() at Volo.Abp.AuditLogging.Blazor.Pages.AuditLogging.AuditLogs.OnDataGridReadAsync(DataGridReadDataEventArgs1 e) at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Blazorise.DataGrid.DataGrid1.HandleReadData(CancellationToken cancellationToken) at Blazorise.DataGrid.DataGrid1.HandleReadData(CancellationToken cancellationToken) at Blazorise.DataGrid.DataGrid1.Reload(CancellationToken cancellationToken) at Blazorise.DataGrid.DataGrid`1.OnAfterRenderAsync(Boolean firstRender) [20:51:44 ERR] Unhandled exception in circuit 'UDY2gjyaAmu646YhqFBUT1s6eywtV8qqhqWc8WpHq1E'.
  • Steps to reproduce the issue:"
  1. Add Azure SignalR configuration following https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/server?view=aspnetcore-5.0
  2. if you run localy set the folllowing enviromental variable so SignalR configuration will be enabled. ASPNETCORE_HOSTINGSTARTUPASSEMBLIES = Microsoft.Azure.SignalR
  3. Open the app and navigate to another page/view

6 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share a simple project to reproduce? liming.ma@volosoft.com

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share a ConnectionString for test?

    "ConnectionString": "Endpoint=https://<signalr-endpoint>.service.signalr.net;AccessKey=<SignalRAccessKey>;Version=1.0;",

  • User Avatar
    0
    ysemykin created

    Hi, I can't share the connection string on public board.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    liming.ma@volosoft.com

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Try this

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var hostingEnvironment = context.Services.GetHostingEnvironment();
        var configuration = context.Services.GetConfiguration();
    
        context.Services.AddSignalR(options =>
        {
            options.AddFilter<AbpSignalRFilter>();
        }).AddAzureSignalR(options =>
        {
            options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required;
            options.ConnectionString = "Endpoint=.....;";
        });
    }
    
    public class AbpSignalRFilter : IHubFilter
    {
        public async ValueTask<object> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
        {
            var currentPrincipalAccessor = invocationContext.ServiceProvider.GetRequiredService<ICurrentPrincipalAccessor>();
            using (currentPrincipalAccessor.Change(invocationContext.Context.User))
            {
                return await next(invocationContext);
            }
        }
    
        // Optional method
        public Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next)
        {
            return next(context);
        }
    
        // Optional method
        public Task OnDisconnectedAsync(
            HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next)
        {
            return next(context, exception);
        }
    }
    
    
  • User Avatar
    0
    ysemykin created

    Hi,

    It looks like the issue was resolved.

    Thanks, Yaroslav

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11