{"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":"error","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/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/NavigationManager.cs#L551-L587","documentation":"Thrown by the default virtual SetNavigationLockState when the first location-changing handler is registered. NavigationLock support requires the host to physically suppress URI changes until NotifyLocationChangingAsync confirms them; the base class cannot do that, so it demands an override. Without the override, registering a NavigationLock would silently no-op and break the contract.","triggerScenarios":"RegisterLocationChangingHandler is called and the handler list transitions from empty to one entry, which calls SetNavigationLockState(true). If the concrete NavigationManager type does not override SetNavigationLockState, this NotSupportedException fires immediately on first registration.","commonSituations":"A test or custom host subclasses NavigationManager directly and exercises NavigationLock or RegisterLocationChangingHandler; a third-party Blazor host (e.g. a non-Microsoft MAUI/gtk host) that has not implemented navigation locking.","solutions":["Override SetNavigationLockState(bool) in your NavigationManager subclass to actually enable/disable interception in your host.","Use the built-in Server/WebAssembly NavigationManager implementations, which already override it.","Do not call RegisterLocationChangingHandler (or render a NavigationLock component) against a manager that does not support locks.","In tests, use the framework test double (e.g. FakeNavigationManager or a derived RemoteNavigationManager) that supplies the overrides."],"exampleFix":"// before: subclass missing the override, registering a lock throws\npublic class CustomNavManager : NavigationManager { }\n// _ = manager.RegisterLocationChangingHandler(...); // throws\n\n// after: override so the host honors the lock flag\npublic class CustomNavManager : NavigationManager\n{\n    private bool _locked;\n    protected override void SetNavigationLockState(bool value) => _locked = value;\n}","handlingStrategy":"validation","validationCode":"var t = navManager.GetType();\nvar overriden = t.GetMethod(nameof(NavigationManager.SetNavigationLockState), BindingFlags.Instance | BindingFlags.NonPublic)!.DeclaringType != typeof(NavigationManager);\nif (!overriden) throw new NotSupportedException($\"{t.Name} cannot host navigation locks: override SetNavigationLockState.\");","typeGuard":null,"tryCatchPattern":"try { manager.RegisterLocationChangingHandler(handler); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"SetNavigationLockState\"))\n{ /* use a capable manager or skip the lock */ }","preventionTips":["Use the framework managers in production.","In a custom host, override SetNavigationLockState and physically block URI changes while locked.","Do not render NavigationLock components against managers that lack lock support."],"tags":["blazor","routing","navigation-lock","extensibility"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}