{"record":{"id":"02a4ab93dca559b3","repo":"dotnet/aspnetcore","slug":"to-support-navigation-locks-gettype-name-must-02a4ab","errorCode":null,"errorMessage":"To support navigation locks, {GetType().Name} must override {nameof(SetNavigationLockState)}","messagePattern":"To support navigation locks, (.+?) must override (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"critical","filePath":"src/Components/Components/src/NavigationManager.cs","lineNumber":569,"sourceCode":"        }\n    }\n\n    /// <summary>\n    /// Handles exceptions thrown in location changing handlers.\n    /// </summary>\n    /// <param name=\"ex\">The exception to handle.</param>\n    /// <param name=\"context\">The context passed to the handler.</param>\n    protected virtual void HandleLocationChangingHandlerException(Exception ex, LocationChangingContext context)\n        => throw new InvalidOperationException($\"To support navigation locks, {GetType().Name} must override {nameof(HandleLocationChangingHandlerException)}\");\n\n    /// <summary>\n    /// Sets whether navigation is currently locked. If it is, then implementations should not update <see cref=\"Uri\"/> and call\n    /// <see cref=\"NotifyLocationChanged(bool)\"/> until they have first confirmed the navigation by calling\n    /// <see cref=\"NotifyLocationChangingAsync(string, string?, bool)\"/>.\n    /// </summary>\n    /// <param name=\"value\">Whether navigation is currently locked.</param>\n    protected virtual void SetNavigationLockState(bool value)\n        => throw new NotSupportedException($\"To support navigation locks, {GetType().Name} must override {nameof(SetNavigationLockState)}\");\n\n    /// <summary>\n    /// Registers a handler to process incoming navigation events.\n    /// </summary>\n    /// <param name=\"locationChangingHandler\">The handler to process incoming navigation events.</param>\n    /// <returns>An <see cref=\"IDisposable\"/> that can be disposed to unregister the location changing handler.</returns>\n    public IDisposable RegisterLocationChangingHandler(Func<LocationChangingContext, ValueTask> locationChangingHandler)\n    {\n        AssertInitialized();\n\n        var isFirstHandler = _locationChangingHandlers.Count == 0;\n\n        _locationChangingHandlers.Add(locationChangingHandler);\n\n        if (isFirstHandler)\n        {\n            SetNavigationLockState(true);\n        }","sourceCodeStart":551,"sourceCodeEnd":587,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/NavigationManager.cs#L551-L587","documentation":"The virtual SetNavigationLockState throws NotSupportedException by default. When the first location-changing handler is registered, NavigationManager calls SetNavigationLockState(true) to enable interception; without an override the lock cannot be engaged.","triggerScenarios":"RegisterLocationChangingHandler is called on a NavigationManager subclass that did not override SetNavigationLockState; the first handler registration triggers the default virtual which throws.","commonSituations":"Custom host NavigationManager opting into navigation locks without implementing the lock-state hook; using NavigationLock component on a platform whose NavigationManager is incomplete.","solutions":["Override protected override void SetNavigationLockState(bool value) in your NavigationManager subclass to enable/disable interception with the host (e.g. JS interop call).","Do not register location-changing handlers if your host does not support locks.","Port the override from the framework's RemoteNavigationManager."],"exampleFix":"// before\npublic class MyNavManager : NavigationManager { /* no override */ }\n\n// after\npublic class MyNavManager : NavigationManager\n{\n    protected override void SetNavigationLockState(bool value)\n        => _jsRuntime.InvokeVoidAsync(\"myNav.setLock\", value);\n}","handlingStrategy":"type-guard","validationCode":"static bool SupportsSetNavigationLockState(NavigationManager nm) =>\n    nm.GetType().GetMethod(\"SetNavigationLockState\",\n        BindingFlags.Instance | BindingFlags.NonPublic)?.DeclaringType != typeof(NavigationManager);","typeGuard":"static bool SupportsNavigationLockState(NavigationManager nm) =>\n    nm.GetType().GetMethod(\"SetNavigationLockState\",\n        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)?.DeclaringType != typeof(NavigationManager);","tryCatchPattern":"try { var sub = navManager.RegisterLocationChangingHandler(handler); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"SetNavigationLockState\"))\n{ logger.LogWarning(ex, \"Host NavigationManager lacks lock support\"); }","preventionTips":["Override SetNavigationLockState in subclasses that enable navigation locks.","Gate NavigationLock usage on host capability checks.","Port the override from RemoteNavigationManager when building a custom host."],"tags":["blazor","navigation","navigation-lock","extensibility","subclassing"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}