Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/Http/Http.Extensions/src/RequestDelegateFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public static partial class RequestDelegateFactory
private static readonly string[] FormFileContentType = new[] { "multipart/form-data" };
private static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
private static readonly string[] PlaintextContentType = new[] { "text/plain" };
private static readonly Type[] StringTypes = new[] {typeof(string), typeof(StringValues), typeof(StringValues?) };

/// <summary>
/// Returns metadata inferred automatically for the <see cref="RequestDelegate"/> created by <see cref="Create(Delegate, RequestDelegateFactoryOptions?, RequestDelegateMetadataResult?)"/>.
Expand Down Expand Up @@ -791,11 +792,11 @@ private static Expression CreateArgument(ParameterInfo parameter, RequestDelegat
// For complex types, leverage the shared form binding infrastructure. For example,
// shared form binding does not currently only supports types that implement IParsable
// while RDF's binding implementation supports all TryParse implementations.
var useSimpleBinding = parameter.ParameterType == typeof(string) ||
parameter.ParameterType == typeof(StringValues) ||
parameter.ParameterType == typeof(StringValues?) ||
var useSimpleBinding = StringTypes.Contains(parameter.ParameterType) ||
ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType) ||
(parameter.ParameterType.IsArray && ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType.GetElementType()!));
(parameter.ParameterType.IsArray &&
(StringTypes.Contains(parameter.ParameterType.GetElementType()) ||
ParameterBindingMethodCache.Instance.HasTryParseMethod(parameter.ParameterType.GetElementType()!)));
hasTryParse = useSimpleBinding;
return useSimpleBinding
? BindParameterFromFormItem(parameter, formAttribute.Name ?? parameter.Name, factoryContext)
Expand Down
22 changes: 22 additions & 0 deletions src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,28 @@ public async Task RequestDelegateHandlesNullableStringValuesFromExplicitQueryStr
Assert.Null(httpContext.Items["form"]);
}

[Fact]
public async Task RequestDelegateHandlesFromFormStringArrayParameter()
{
var httpContext = CreateHttpContext();
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
{
["form"] = new(new[] { "1", "2", "3" })
});

var factoryResult = RequestDelegateFactory.Create(
(HttpContext context, [FromForm(Name = "form")] string[] formValues) =>
{
context.Items["form"] = formValues;
});

var requestDelegate = factoryResult.RequestDelegate;

await requestDelegate(httpContext);

Assert.Equal(new StringValues(new[] { "1", "2", "3" }), httpContext.Items["form"]!);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Assert.Equal(new StringValues(new[] { "1", "2", "3" }), httpContext.Items["form"]!);
var parameterBindingMetadata = factoryResult.EndpointMetadata
.FirstOrDefault(e => e is ParameterBindingMetadata metadata &&
metadata.Name == "formValues") as ParameterBindingMetadata;
Assert.NotNull(parameterBindingMetadata);
Assert.Equal(typeof(string[]), parameterBindingMetadata.ParameterInfo.ParameterType);
Assert.Equal(new StringValues(new[] { "1", "2", "3" }), httpContext.Items["form"]!);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commited suggestion

}

[Fact]
public async Task RequestDelegateCanAwaitValueTasksThatAreNotImmediatelyCompleted()
{
Expand Down
Loading