Open Closed

Blazor server page jump error #6280


User avatar
0
327992883@qq.com created
  • ABP Framework version: v7.2.3
  • UI Type: Blazor Server
  • Database System: EF Core
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes
  • Exception message and full stack trace:
  • [18:21:45 DBG] Found in the cache: pn:U,pk:91a14806-b5c0-aa82-b0cb-3a0c6095438a,n:Inventories.OutboundOrder.Create [18:21:45 DBG] PermissionStore.GetCacheItemAsync: pn:R,pk:admin,n:Inventories.OutboundOrder.Create [18:21:45 DBG] Found in the cache: pn:U,pk:91a14806-b5c0-aa82-b0cb-3a0c6095438a,n:Inventories.OutboundOrderDetail [18:21:45 DBG] PermissionStore.GetCacheItemAsync: pn:R,pk:admin,n:Inventories.OutboundOrderDetail [18:21:45 DBG] Found in the cache: pn:R,pk:admin,n:Inventories.OutboundOrder.Create [18:21:45 DBG] Found in the cache: pn:R,pk:admin,n:Inventories.OutboundOrderDetail [18:21:47 WRN] Unhandled exception rendering component: Cannot access a disposed object. Object name: 'Loda.Abp.StoreManage.Inventories.Blazor.Pages.Inventories.OutboundOrder'. System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Loda.Abp.StoreManage.Inventories.Blazor.Pages.Inventories.OutboundOrder'. at Loda.Abp.Components.LodaComponentBase.get_ScopedServices() at Loda.Abp.Components.LodaComponentBase.LazyGetRequiredService[TRef](Type serviceType, TRef& reference) at Loda.Abp.Components.LodaComponentBase.LazyGetRequiredService[TService](TService& reference) at Loda.Abp.Components.LodaComponentBase.get_LoggerFactory() at Loda.Abp.Components.LodaComponentBase.<get__lazyLogger>b__37_0() at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue() at Loda.Abp.Components.LodaComponentBase.get_Logger() at Loda.Abp.Components.LodaComponentBase.OnErrorAsync(Exception exception) at Microsoft.AspNetCore.Components.ErrorBoundaryBase.Microsoft.AspNetCore.Components.IErrorBoundary.HandleException(Exception exception) at Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleExceptionViaErrorBoundary(Exception error, ComponentState errorSourceOrNull) [18:21:47 ERR] Unhandled exception in circuit 'LIOY43OPH3utkSu22ZegyguiJKfC3kmBReCuWQ8lhY8'. System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Loda.Abp.StoreManage.Inventories.Blazor.Pages.Inventories.OutboundOrder'. at Loda.Abp.Components.LodaComponentBase.get_ScopedServices() at Loda.Abp.Components.LodaComponentBase.LazyGetRequiredService[TRef](Type serviceType, TRef& reference) at Loda.Abp.Components.LodaComponentBase.LazyGetRequiredService[TService](TService& reference) at Loda.Abp.Components.LodaComponentBase.get_LoggerFactory() at Loda.Abp.Components.LodaComponentBase.<get__lazyLogger>b__37_0() at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue() at Loda.Abp.Components.LodaComponentBase.get_Logger() at Loda.Abp.Components.LodaComponentBase.OnErrorAsync(Exception exception) at Microsoft.AspNetCore.Components.ErrorBoundaryBase.Microsoft.AspNetCore.Components.IErrorBoundary.HandleException(Exception exception) at Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleExceptionViaErrorBoundary(Exception error, ComponentState errorSourceOrNull) [18:21:47 INF] Executed endpoint '/_blazor' [18:21:47 INF] Request finished HTTP/2 CONNECT https://localhost:44354/_blazor?id=XaSAouEAb9hvCj8WlD56sA - - - 200 - - 5496.7929ms [18:21:47 INF] Connection id "0HMVLFE759C7D", Request id "0HMVLFE759C7D:0000003B": the application completed without reading the entire request body.
  • Steps to reproduce the issue: My blazor server will throw an exception when jumping from one page to another, but refreshing any of the pages directly will not cause an exception. The exception is only when jumping, and it seems to be related to resource release.

LodaComponentBase.cs,This is the base class for all our component pages

using Blazorise.Localization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using Volo.Abp;
using Volo.Abp.AspNetCore.Components.Alerts;
using Volo.Abp.AspNetCore.Components.ExceptionHandling;
using Volo.Abp.AspNetCore.Components.Messages;
using Volo.Abp.AspNetCore.Components.Notifications;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Timing;
using Volo.Abp.Users;

namespace Loda.Abp.Components
{
    public class LodaComponentBase : ErrorBoundary, IDisposable
    {
        [Inject] public IUiMessageService UiMessageService { get; set; }
        [Inject]
        public Blazorise.Localization.ITextLocalizerService LocalizationService { get; set; }

        public LodaComponentBase()
        {

        }
        protected override Task OnInitializedAsync()
        {
            var IetfLanguageTag = CultureInfo.CurrentCulture.IetfLanguageTag;
            if (IetfLanguageTag.Split("-").Length > 1)
            {
                var split = IetfLanguageTag.Split("-")[0];
                LocalizationService.ChangeLanguage(split);
            }
            return base.OnInitializedAsync();
        }


        protected override Task OnErrorAsync(Exception exception)
        {
            
            Logger.LogError(new EventId(0, "全局异常"), exception: exception, message: exception.Message);
            if (exception is AbpRemoteCallException)
            {
                var ex = exception as AbpRemoteCallException;

                //401错误返回原来的异常处理机制,让前台做跳转
                if (ex.HttpStatusCode == (int)HttpStatusCode.Unauthorized) return base.OnErrorAsync(exception);

                return UiMessageService.Info(ex.Error.Message, ex.Error.Code);
            }

            //await base.OnErrorAsync(exception);             
            if (exception is UserFriendlyException)
            {
                var ex = exception as UserFriendlyException;
                return UiMessageService.Info(ex.Message);
            }

            if (exception is BusinessException)
            {
                var ex = exception as BusinessException;
                return UiMessageService.Warn(ex.Message, ex.Code);
            }
            return UiMessageService.Error(exception.Message);
        }

        //OwningComponentBase 基类部分

        private AsyncServiceScope? _scope;

        [Inject] IServiceScopeFactory ScopeFactory { get; set; } = default!;

        protected bool IsDisposed { get; private set; }

        protected IServiceProvider ScopedServices
        {
            get
            {
                if (ScopeFactory == null)
                {
                    throw new InvalidOperationException("Services cannot be accessed before the component is initialized.");
                }

                ObjectDisposedException.ThrowIf(IsDisposed, this);

                _scope ??= ScopeFactory.CreateAsyncScope();
                return _scope.Value.ServiceProvider;
            }
        }

        void IDisposable.Dispose()
        {
            if (!IsDisposed)
            {
                _scope?.Dispose();
                _scope = null;
                Dispose(disposing: true);
                IsDisposed = true;
            }
        }

        /// <inheritdoc />
        protected virtual void Dispose(bool disposing)
        {
        }

        //---------------------------------------------

        //AbpComponentBase基类部分
        protected IStringLocalizerFactory StringLocalizerFactory => LazyGetRequiredService(ref _stringLocalizerFactory);
        private IStringLocalizerFactory _stringLocalizerFactory;

        protected IStringLocalizer L
        {
            get
            {
                if (_localizer == null)
                {
                    _localizer = CreateLocalizer();
                }

                return _localizer;
            }
        }
        private IStringLocalizer _localizer;

        protected Type LocalizationResource
        {
            get => _localizationResource;
            set
            {
                _localizationResource = value;
                _localizer = null;
            }
        }
        private Type _localizationResource = typeof(DefaultResource);

        protected ILogger Logger => _lazyLogger.Value;
        private Lazy<ILogger> _lazyLogger => new Lazy<ILogger>(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true);

        protected ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory);
        private ILoggerFactory _loggerFactory;

        protected IAuthorizationService AuthorizationService => LazyGetRequiredService(ref _authorizationService);
        private IAuthorizationService _authorizationService;

        protected ICurrentUser CurrentUser => LazyGetRequiredService(ref _currentUser);
        private ICurrentUser _currentUser;

        protected ICurrentTenant CurrentTenant => LazyGetRequiredService(ref _currentTenant);
        private ICurrentTenant _currentTenant;

        protected IUiMessageService Message => LazyGetNonScopedRequiredService(ref _message);
        private IUiMessageService _message;

        protected IUiNotificationService Notify => LazyGetNonScopedRequiredService(ref _notify);
        private IUiNotificationService _notify;

        protected IUserExceptionInformer UserExceptionInformer => LazyGetNonScopedRequiredService(ref _userExceptionInformer);
        private IUserExceptionInformer _userExceptionInformer;

        protected IAlertManager AlertManager => LazyGetNonScopedRequiredService(ref _alertManager);
        private IAlertManager _alertManager;

        protected IClock Clock => LazyGetNonScopedRequiredService(ref _clock);
        private IClock _clock;

        protected AlertList Alerts => AlertManager.Alerts;

        protected IObjectMapper ObjectMapper
        {
            get
            {
                if (_objectMapper != null)
                {
                    return _objectMapper;
                }

                if (ObjectMapperContext == null)
                {
                    return LazyGetRequiredService(ref _objectMapper);
                }

                return LazyGetRequiredService(
                    typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
                    ref _objectMapper
                );
            }
        }

        private IObjectMapper _objectMapper;

        protected Type ObjectMapperContext { get; set; }

        protected TService LazyGetRequiredService<TService>(ref TService reference) => LazyGetRequiredService(typeof(TService), ref reference);

        protected TRef LazyGetRequiredService<TRef>(Type serviceType, ref TRef reference)
        {
            if (reference == null)
            {
                reference = (TRef)ScopedServices.GetRequiredService(serviceType);
            }

            return reference;
        }

        protected TService LazyGetService<TService>(ref TService reference) => LazyGetService(typeof(TService), ref reference);

        protected TRef LazyGetService<TRef>(Type serviceType, ref TRef reference)
        {
            if (reference == null)
            {
                reference = (TRef)ScopedServices.GetService(serviceType);
            }

            return reference;
        }

        protected TService LazyGetNonScopedRequiredService<TService>(ref TService reference) => LazyGetNonScopedRequiredService(typeof(TService), ref reference);

        protected TRef LazyGetNonScopedRequiredService<TRef>(Type serviceType, ref TRef reference)
        {
            if (reference == null)
            {
                reference = (TRef)NonScopedServices.GetRequiredService(serviceType);
            }

            return reference;
        }

        protected TService LazyGetNonScopedService<TService>(ref TService reference) => LazyGetNonScopedService(typeof(TService), ref reference);

        protected TRef LazyGetNonScopedService<TRef>(Type serviceType, ref TRef reference)
        {
            if (reference == null)
            {
                reference = (TRef)NonScopedServices.GetService(serviceType);
            }

            return reference;
        }

        [Inject]
        protected IServiceProvider NonScopedServices { get; set; }

        protected virtual IStringLocalizer CreateLocalizer()
        {
            if (LocalizationResource != null)
            {
                return StringLocalizerFactory.Create(LocalizationResource);
            }

            var localizer = StringLocalizerFactory.CreateDefaultOrNull();
            if (localizer == null)
            {
                throw new AbpException($"Set {nameof(LocalizationResource)} or define the default localization resource type (by configuring the {nameof(AbpLocalizationOptions)}.{nameof(AbpLocalizationOptions.DefaultResourceType)}) to be able to use the {nameof(L)} object!");
            }

            return localizer;
        }

        protected virtual async Task HandleErrorAsync(Exception exception)
        {
            Logger.LogException(exception);
            await InvokeAsync(async () =>
            {
                await UserExceptionInformer.InformAsync(new UserExceptionInformerContext(exception));
                StateHasChanged();
            });
        }
    }
}

4 Answer(s)
  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hello ,

    Please Check this https://support.abp.io/QA/Questions/5289/Object-Disposed-Exception-in-Blazor-Server-App

    Thanks,

  • User Avatar
    0
    327992883@qq.com created

    According to the address you provided, I created MyUserManagement according to the instructions in the link, but the Razor file in it was abnormal. https://gist.github.com/realLiangshiwei/bc88b4c7a9b1d7757084da05f179e5fe

    This file appears to be too old to be used Is there any good solution? Or can you tell me what is the reason for this problem and how to solve it?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    As I said before, this is Blazor's design. When switching pages, the component will be disposed, but the previous component code is still executing.

    You can check my PR: https://github.com/abpframework/abp/pull/17040

  • User Avatar
    0
    327992883@qq.com created

    thank you

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