Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 21, 2025

Fixes #63692

Problem

When developers override PageModel lifecycle methods (OnPageHandlerExecuting, OnPageHandlerExecuted, OnPageHandlerSelected) in their Razor Pages, these overridden methods were being incorrectly discovered as page handlers. This resulted in them being parsed with unexpected HTTP methods and handler names:

  • OnPageHandlerExecutingHttpMethod = "Page", HandlerName = "HandlerExecuting"
  • OnPageHandlerExecutedHttpMethod = "Page", HandlerName = "HandlerExecuted"
  • OnPageHandlerSelectedHttpMethod = "Page", HandlerName = "HandlerSelected"

Root Cause

The IsHandler() method in DefaultPageApplicationModelPartsProvider excluded methods declared directly on PageModel using:

if (declaringType == typeof(PageModel))
{
    return false;
}

However, when a developer overrides these methods in a derived class, the DeclaringType is the derived class, not PageModel, causing the check to fail and allowing these lifecycle methods to be treated as handlers.

Solution

Changed the exclusion check to use GetBaseDefinition() to trace back to the original method definition:

// Exclude methods declared on PageModel (including overrides)
if (methodInfo.GetBaseDefinition().DeclaringType == typeof(PageModel))
{
    return false;
}

This ensures that overridden lifecycle methods from PageModel are properly excluded from handler discovery.

Testing

Added regression test PopulateHandlerMethods_Ignores_OverriddenPageModelLifecycleMethods that verifies:

  • Overridden lifecycle methods (OnPageHandlerExecuting, OnPageHandlerExecuted, OnPageHandlerSelected) are NOT discovered as handlers
  • Legitimate page handlers like OnGet continue to be discovered correctly

All existing tests pass, confirming no behavioral changes for legitimate handler methods.

Original prompt

This PR addresses issue #63692: Overridden Razor Page lifecycle methods (PageModel.OnPageHandlerExecuting / OnPageHandlerExecuted / OnPageHandlerSelected) were being discovered as potential page handlers unless explicitly annotated with [NonHandler].

Root Cause:
DefaultPageApplicationModelPartsProvider.IsHandler() excluded methods when methodInfo.DeclaringType == typeof(PageModel). This fails for overrides, whose DeclaringType is the user-derived PageModel subclass. Thus overrides passed the exclusion and were parsed as handlers: e.g. OnPageHandlerExecuting => HttpMethod = "Page", HandlerName = "HandlerExecuting".

Minimal Fix Applied:
Replace the existing PageModel exclusion check with one that inspects methodInfo.GetBaseDefinition().DeclaringType. This ensures overrides of PageModel lifecycle methods are excluded without changing other logic.

Code Changes:

  1. src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs

    • Modify the PageModel exclusion line: if (declaringType == typeof(PageModel)) -> if (methodInfo.GetBaseDefinition().DeclaringType == typeof(PageModel)).
  2. src/Mvc/Mvc.RazorPages/test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs

    • Add a new regression test PopulateHandlerMethods_Ignores_OverriddenPageModelLifecycleMethods verifying that overriding lifecycle methods does not result in them being treated as handlers; only a legitimate handler (OnGet) is discovered.

Test Details:
The new test defines a ModelOverridingPageModelLifecycle : PageModel with overrides of lifecycle hooks plus an OnGet handler. After PopulateHandlerMethods, only one handler (OnGet) should be present. Prior to the fix, OnPageHandlerExecuting would have been included.

Acceptance:
Run existing Razor Pages unit test suite; the new test should pass. No behavior changes expected for legitimate handler methods. Extremely low risk.

Please implement the described changes and open a PR.

Referenced Issue: #63692

This pull request was created as a result of the following prompt from Copilot chat.

This PR addresses issue #63692: Overridden Razor Page lifecycle methods (PageModel.OnPageHandlerExecuting / OnPageHandlerExecuted / OnPageHandlerSelected) were being discovered as potential page handlers unless explicitly annotated with [NonHandler].

Root Cause:
DefaultPageApplicationModelPartsProvider.IsHandler() excluded methods when methodInfo.DeclaringType == typeof(PageModel). This fails for overrides, whose DeclaringType is the user-derived PageModel subclass. Thus overrides passed the exclusion and were parsed as handlers: e.g. OnPageHandlerExecuting => HttpMethod = "Page", HandlerName = "HandlerExecuting".

Minimal Fix Applied:
Replace the existing PageModel exclusion check with one that inspects methodInfo.GetBaseDefinition().DeclaringType. This ensures overrides of PageModel lifecycle methods are excluded without changing other logic.

Code Changes:

  1. src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs

    • Modify the PageModel exclusion line: if (declaringType == typeof(PageModel)) -> if (methodInfo.GetBaseDefinition().DeclaringType == typeof(PageModel)).
  2. src/Mvc/Mvc.RazorPages/test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs

    • Add a new regression test PopulateHandlerMethods_Ignores_OverriddenPageModelLifecycleMethods verifying that overriding lifecycle methods does not result in them being treated as handlers; only a legitimate handler (OnGet) is discovered.

Test Details:
The new test defines a ModelOverridingPageModelLifecycle : PageModel with overrides of lifecycle hooks plus an OnGet handler. After PopulateHandlerMethods, only one handler (OnGet) should be present. Prior to the fix, OnPageHandlerExecuting would have been included.

Acceptance:
Run existing Razor Pages unit test suite; the new test should pass. No behavior changes expected for legitimate handler methods. Extremely low risk.

Please implement the described changes and open a PR.

Referenced Issue: #63692


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI changed the title [WIP] Fix Razor Page handler discovery for overridden lifecycle methods Fix: Prevent overridden PageModel lifecycle methods from being discovered as handlers Oct 21, 2025
Copilot finished work on behalf of MackinnonBuck October 21, 2025 20:20
@Copilot Copilot AI requested a review from MackinnonBuck October 21, 2025 20:20
@MackinnonBuck MackinnonBuck marked this pull request as ready for review October 22, 2025 16:06
@MackinnonBuck MackinnonBuck requested a review from a team as a code owner October 22, 2025 16:06
@Copilot Copilot AI review requested due to automatic review settings October 22, 2025 16:06
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a bug where overridden PageModel lifecycle methods were incorrectly being discovered as page handlers, causing them to be treated as handler methods with unexpected HTTP method and handler name values.

Key Changes:

  • Modified the handler discovery logic to use GetBaseDefinition() to properly exclude overridden lifecycle methods from PageModel
  • Added a regression test to verify that overridden lifecycle methods are not treated as handlers

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs Updated the IsHandler method to check the base definition's declaring type, ensuring overridden PageModel lifecycle methods are excluded
src/Mvc/Mvc.RazorPages/test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs Added regression test verifying that overridden lifecycle methods are not discovered as handlers while legitimate handlers like OnGet are still discovered

@MackinnonBuck MackinnonBuck merged commit 5b64506 into main Oct 22, 2025
30 checks passed
@MackinnonBuck MackinnonBuck deleted the copilot/fix-razor-page-handler-discovery branch October 22, 2025 22:06
@dotnet-policy-service dotnet-policy-service bot added this to the 11.0-preview1 milestone Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overridden razor page lifecycle methods detected as page handlers

3 participants