Skip to content

C#: Improve ASP.NET Core MVC controller discovery - #22265

Open
JarLob wants to merge 11 commits into
github:mainfrom
JarLob:aspnetcore-controller-discovery
Open

C#: Improve ASP.NET Core MVC controller discovery#22265
JarLob wants to merge 11 commits into
github:mainfrom
JarLob:aspnetcore-controller-discovery

Conversation

@JarLob

@JarLob JarLob commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Improve ASP.NET Core MVC controller and action discovery so that it more closely
matches the framework's runtime behavior.

Previously, the ASP.NET Core controller abstraction combined broad heuristics
needed for controller response helpers with the stricter concept of a
runtime-discovered MVC controller. This could classify unrelated
*Controller classes as remote-input sources and did not fully account for
application parts, endpoint mappings, or inherited action methods.

This change:

  • Separates broad controller helper ownership from runtime controller discovery,
    preserving redirect and response-helper sink coverage.
  • Requires controllers to be public, concrete, top-level, and closed classes.
  • Recognizes controller identity through the Controller suffix,
    ControllerBase, or an inherited [Controller] attribute.
  • Honors inherited [NonController] exclusions.
  • Restricts suffix-only POCO controllers using MVC registration,
    application-part, and endpoint-mapping evidence.
  • Models application parts from the application assembly,
    [ApplicationPart], and explicit AddApplicationPart calls.
  • Distinguishes attribute routing from conventional controller routing.
  • Includes inherited action methods while excluding non-public, static,
    abstract, generic, [NonAction], object override, and
    IDisposable.Dispose methods.
  • Excludes explicitly service-injected action parameters from remote-input
    modeling because they are resolved from application services rather than
    supplied by the HTTP client.

Classic ASP.NET MVC and Web API controller modeling is unchanged.

Limitations

This remains a static approximation of ASP.NET Core MVC discovery:

  • Suffix-only POCO controllers require visible MVC registration,
    application-part, and endpoint-mapping evidence. They may be missed when this
    configuration is in unextracted code or external framework helpers.
  • Application-part modeling covers the application assembly, generated
    [ApplicationPart] attributes, and direct
    AddApplicationPart(typeof(T).Assembly) calls. Custom feature providers,
    arbitrary ConfigureApplicationPartManager mutations, reflection, and
    dynamically loaded plugin assemblies are not modeled.
  • Endpoint modeling recognizes the standard ASP.NET Core attribute and
    conventional routing APIs. Custom routing mechanisms are only recognized
    when their implementation contains an extracted call to one of those APIs.
  • Classes deriving from ControllerBase or carrying an inherited
    [Controller] attribute retain a conservative fallback and do not require
    visible registration or routing evidence.
  • Service-parameter exclusion covers explicit IFromServiceMetadata and
    [FromKeyedServices] attributes, including derived attributes. Runtime
    inference of unannotated service parameters from the DI container is not
    modeled.

Copilot AI review requested due to automatic review settings July 31, 2026 14:53
@JarLob
JarLob requested a review from a team as a code owner July 31, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Improves ASP.NET Core MVC controller/action discovery while preserving response-helper sink coverage.

Changes:

  • Adds registration, application-part, routing, controller, and action discovery rules.
  • Excludes service-injected parameters from remote-input modeling.
  • Adds library and multi-project integration coverage.
Show a summary per file
File Description
csharp/ql/test/library-tests/frameworks/microsoft/AspNetCoreActions.ql Queries discovered controller actions.
csharp/ql/test/library-tests/frameworks/microsoft/AspNetCoreActions.expected Records expected actions.
csharp/ql/test/library-tests/frameworks/microsoft/AspNetCore.expected Updates expected controllers.
csharp/ql/test/library-tests/frameworks/microsoft/AspNetCore.cs Adds controller and action cases.
csharp/ql/test/library-tests/dataflow/flowsources/aspremote/aspRemoteFlowSource.expected Updates expected remote sources.
csharp/ql/test/library-tests/dataflow/flowsources/aspremote/AspRemoteFlowSource.cs Tests service-injected parameters.
csharp/ql/lib/semmle/code/csharp/security/dataflow/UrlRedirectQuery.qll Uses broad response-helper ownership.
csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll Excludes service-injected action parameters.
csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll Implements refined discovery.
csharp/ql/lib/change-notes/2026-07-31-aspnet-core-controller-discovery.md Documents the analysis improvement.
.../WebApp/WebPocoController.cs Adds an application controller.
.../WebApp/WebApp.csproj Defines the main web project.
.../WebApp/Program.cs Registers MVC, application parts, and routing.
.../WebApp/ApplicationParts.cs Declares a generated application part.
.../Unrelated/Unrelated.csproj Defines a non-web project.
.../Unrelated/ThrottlingController.cs Tests unrelated suffix exclusion.
.../UnmappedWebApp/UnmappedWebApp.csproj Defines an unmapped web project.
.../UnmappedWebApp/UnmappedPocoController.cs Tests endpoint-evidence requirements.
.../UnmappedWebApp/StructuralController.cs Tests structural fallback discovery.
.../UnmappedWebApp/Program.cs Registers MVC without endpoint mapping.
.../aspnetcore_controller_discovery/test.py Builds all integration fixtures.
.../IncludedControllers/IncludedControllers.csproj Defines an explicitly included part.
.../IncludedControllers/IncludedController.cs Adds the explicitly included controller.
.../aspnetcore_controller_discovery/global.json Pins the .NET SDK.
.../GeneratedControllers/GeneratedControllers.csproj Defines an attributed application part.
.../GeneratedControllers/GeneratedController.cs Adds the attributed controller.
.../aspnetcore_controller_discovery/Controllers.ql Queries discovered controllers.
.../aspnetcore_controller_discovery/Controllers.expected Records integration expectations.
.../AttributeWebApp/Program.cs Configures attribute routing.
.../AttributeWebApp/ConventionOnlyController.cs Tests convention-only exclusion.
.../AttributeWebApp/AttributeWebApp.csproj Defines the attribute-routed app.
.../AttributeWebApp/AttributePocoController.cs Tests attribute-routed POCO discovery.

Review details

  • Files reviewed: 32/32 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Suppressed comments (1)

csharp/ql/integration-tests/all-platforms/aspnetcore_controller_discovery/WebApp/Program.cs:11

  • The advertised support for standard conventional controller endpoints is incomplete: this test only covers MapControllerRoute, while ASP.NET Core also routes to MVC actions through MapFallbackToController and MapFallbackToAreaController. A suffix-only POCO exposed exclusively by either fallback API is therefore omitted from discovery. Please recognize those endpoint methods (ideally using their controller argument to avoid broadening every controller) and add an integration scenario for them.
app.MapControllerRoute("default", "{controller}/{action}");
  • Files reviewed: 32/32 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 35/35 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

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.

3 participants