Skip to content

Conversation

@wahab-cide
Copy link

Fix collection interface binding with AsParameters and FromForm

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Summary

Fix collection interface binding with AsParameters and FromForm

Description

This change extends simple binding to support collection interface types (IEnumerable<T>, IList<T>, ICollection<T>, List<T>) when used as properties in [AsParameters] classes with [FromForm].

Problem

Previously, these types caused InvalidOperationException because the framework attempted to use complex form binding (FormDataMapper) which cannot instantiate interface types. This issue only affected properties in [AsParameters] classes, not direct parameters.

Example that failed before this fix:

app.MapPost("/api/documents", ([AsParameters] DocumentUploadRequest request) =>
{
    return Results.Ok(new { Count = request.Values?.Count() ?? 0 });
});

public class DocumentUploadRequest
{
    public IFormFile? File { get; set; }

    [FromForm]
    public IEnumerable<int> Values { get; set; }  // threw InvalidOperationException
}

This PR

This PR follows the same pattern as PR #63072 (which fixed string[] arrays) by extending simple binding to handle collection interfaces:

Key Changes:

  1. Added IsBindableCollectionInterface() helper - Detects collection interface types that can be treated as arrays
  2. Extended binding decision logic - Routes collection interfaces through simple binding when used as AsParameters properties
  3. Updated BindParameterFromValue() - Creates arrays internally and converts them to the target collection type (cast for interfaces, constructor for List<T>)
  4. Updated GetExpressionType() - Made it parameter-aware to treat collection interfaces as string[] only for AsParameters properties
  5. Scoped to PropertyAsParameterInfo - Preserves complex binding for direct [FromForm] parameters to maintain backward compatibility

What Now Works

IEnumerable<T> with [AsParameters] and [FromForm]
IList<T> with [AsParameters] and [FromForm]
ICollection<T> with [AsParameters] and [FromForm]
List<T> with [AsParameters] and [FromForm]

Where T is string or any type with a valid TryParse method.

Backward Compatibility

No breaking changes - All existing tests pass
Scoped fix - Only applies to [AsParameters] properties
Direct parameters unchanged - ([FromForm] List<int> items) still uses complex binding for nested key support like ["[0]"], ["[1]"]

Testing

Added comprehensive unit tests:

  • RequestDelegateHandlesAsParametersWithFromFormIEnumerable - Tests IEnumerable
  • RequestDelegateHandlesAsParametersWithFromFormIList - Tests IList
  • RequestDelegateHandlesAsParametersWithFromFormList - Tests List
  • RequestDelegateHandlesAsParametersWithFromFormIEnumerableString - Tests IEnumerable
  • RequestDelegateHandlesAsParametersWithFromFormIntArray - Tests int[] to verify no regression

All 2,111 tests (2,106 existing + 5 new) pass successfully.

Fixes #62329

   Fixes dotnet#62329

   This change extends simple binding to support collection interface types
   (IEnumerable<T>, IList<T>, ICollection<T>, List<T>) when used as properties
   in [AsParameters] classes with [FromForm].

   Previously, these types caused InvalidOperationException because the framework
   attempted to use complex form binding (FormDataMapper) which cannot instantiate
   interface types.

   The fix:
   - Adds IsBindableCollectionInterface() helper to detect collection interfaces
   - Routes these types through simple binding (like arrays) when used as AsParameters properties
   - Creates arrays internally and converts them to the target collection type
   - Preserves complex binding for direct [FromForm] parameters to maintain backward compatibility
Adds comprehensive tests for IEnumerable<T>, IList<T>, ICollection<T>,
List<T>, and int[] to verify the fix for dotnet#62329 and ensure no regressions.
@github-actions github-actions bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Dec 12, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Dec 12, 2025
@dotnet-policy-service
Copy link
Contributor

Thanks for your PR, @@wahab-cide. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

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

Labels

community-contribution Indicates that the PR has been added by a community member needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

InvalidOperationException when using AsParameters with FromForm and IEnumerable properties

1 participant