Skip to content

Port: Enforce EDM model boundary for open-type property binding in $apply groupby - #2903

Open
WanjohiSammy wants to merge 3 commits into
masterfrom
fix/apply-open-type-model-binding
Open

Port: Enforce EDM model boundary for open-type property binding in $apply groupby#2903
WanjohiSammy wants to merge 3 commits into
masterfrom
fix/apply-open-type-model-binding

Conversation

@WanjohiSammy

@WanjohiSammy WanjohiSammy commented Jul 20, 2026

Copy link
Copy Markdown
Member

Issues

This pull request fixes #xxx.

Description

Ported from: OData/AspNetCoreOData@5e3adee4

When an $apply groupby path crosses an open/dynamic segment, the transformation binder resolved the trailing open-property segment with raw reflection (Type.GetProperty(name)) using the EDM/URI name, binding to any matching public CLR property without consulting the model. A CLR property excluded from the model ([NotMapped] / Ignore() / simply unmodeled) was still resolvable, so its value leaked into groupby results.

Fix (TransformationBinderBase.CreateOpenPropertyAccessExpression). Resolve the open property from the runtime type's dynamic-property container when the name is not an EDM-declared structural property, instead of falling back to CLR reflection. Declared properties bind as before. The dynamic-container access is null-guarded only when QuerySettings.HandleNullPropagation is enabled (the in-memory LINQ-to-Objects path uses HandleNullPropagation.Default → True, so it is guarded).

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

Additional work necessary

If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.

@WanjohiSammy
WanjohiSammy force-pushed the fix/apply-open-type-model-binding branch from 087a13a to 31e1f42 Compare July 20, 2026 13:26
xuzhg
xuzhg previously approved these changes Jul 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown

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 ports a fix to ensure $apply=groupby(...) open-type property binding respects the EDM model boundary, preventing $apply from reflecting and binding to public CLR properties that were intentionally excluded from the model (e.g., via [NotMapped]), which could otherwise leak into grouping results.

Changes:

  • Updated transformation binding to map EDM property names to CLR properties only when the property is declared in the EDM model; otherwise bind via the dynamic property container.
  • Added unit + E2E coverage validating that unmodeled CLR members on open types do not participate in $apply groupby binding/results.
  • Added a guard in dynamic-property-container resolution to avoid null dereferences for nested open paths and surface a cleaner query error.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/DataModel.cs Adds an open-type test model with an EDM-excluded CLR property via [NotMapped].
test/UnitTest/Microsoft.AspNet.OData.Test.Shared/Query/Expressions/AggregationBinderTests.cs Adds a unit test ensuring groupby binds excluded members via the dynamic container rather than CLR reflection.
test/E2ETest/Microsoft.Test.E2E.AspNet.OData/Aggregation/AggregationTests.cs Adds an E2E test validating excluded CLR values don’t show up in $apply=groupby results on open types.
test/E2ETest/Microsoft.Test.E2E.AspNet.OData/Aggregation/AggregationDataModel.cs Introduces an open-type entity with a [NotMapped] CLR member used by the E2E scenario.
test/E2ETest/Microsoft.Test.E2E.AspNet.OData/Aggregation/AggregationController.cs Adds a controller endpoint serving the open-type data for the new E2E test.
src/Microsoft.AspNet.OData.Shared/Query/Expressions/TransformationBinderBase.cs Enforces EDM-boundary property resolution for open-property access during transformation binding.
src/Microsoft.AspNet.OData.Shared/Query/Expressions/ExpressionBinderBase.cs Adds a null guard for open-property sources lacking type references, throwing a cleaner query error.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants