Skip to content

Commit 44a588c

Browse files
committed
Infer that interface parameters are services
1 parent 24a748c commit 44a588c

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

src/Http/Http.Extensions/src/RequestDelegateFactory.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,7 @@ private static Expression CreateArgument(ParameterInfo parameter, FactoryContext
203203
}
204204
else if (parameterCustomAttributes.OfType<IFromBodyMetadata>().FirstOrDefault() is { } bodyAttribute)
205205
{
206-
if (factoryContext.JsonRequestBodyType is not null)
207-
{
208-
throw new InvalidOperationException("Action cannot have more than one FromBody attribute.");
209-
}
210-
211-
factoryContext.JsonRequestBodyType = parameter.ParameterType;
212-
factoryContext.AllowEmptyRequestBody = bodyAttribute.AllowEmpty;
213-
214-
return Expression.Convert(BodyValueExpr, parameter.ParameterType);
206+
return BindParameterFromBody(parameter.ParameterType, bodyAttribute.AllowEmpty, factoryContext);
215207
}
216208
else if (parameter.CustomAttributes.Any(a => typeof(IFromServiceMetadata).IsAssignableFrom(a.AttributeType)))
217209
{
@@ -229,10 +221,14 @@ private static Expression CreateArgument(ParameterInfo parameter, FactoryContext
229221
{
230222
return BindParameterFromRouteValueOrQueryString(parameter, parameter.Name, factoryContext);
231223
}
232-
else
224+
else if (parameter.ParameterType.IsInterface)
233225
{
234226
return Expression.Call(GetRequiredServiceMethod.MakeGenericMethod(parameter.ParameterType), RequestServicesExpr);
235227
}
228+
else
229+
{
230+
return BindParameterFromBody(parameter.ParameterType, allowEmpty: false, factoryContext);
231+
}
236232
}
237233

238234
private static Expression CreateMethodCall(MethodInfo methodInfo, Expression? target, Expression[] arguments) =>
@@ -627,6 +623,19 @@ private static Expression BindParameterFromRouteValueOrQueryString(ParameterInfo
627623
return BindParameterFromValue(parameter, Expression.Coalesce(routeValue, queryValue), factoryContext);
628624
}
629625

626+
private static Expression BindParameterFromBody(Type parameterType, bool allowEmpty, FactoryContext factoryContext)
627+
{
628+
if (factoryContext.JsonRequestBodyType is not null)
629+
{
630+
throw new InvalidOperationException("Action cannot have more than one FromBody attribute.");
631+
}
632+
633+
factoryContext.JsonRequestBodyType = parameterType;
634+
factoryContext.AllowEmptyRequestBody = allowEmpty;
635+
636+
return Expression.Convert(BodyValueExpr, parameterType);
637+
}
638+
630639
private static MethodInfo GetMethodInfo<T>(Expression<T> expr)
631640
{
632641
var mc = (MethodCallExpression)expr.Body;

src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ public async Task RequestDelegatePopulatesUnattributedTryParsableParametersFromR
416416
Assert.Equal(42, httpContext.Items["tryParsable"]);
417417
}
418418

419-
public static object[][] DelegatesWithInvalidAttributes
419+
public static object[][] DelegatesWithAttributesOnNotTryParsableParameters
420420
{
421421
get
422422
{
@@ -434,7 +434,7 @@ void InvalidFromHeader([FromHeader] object notTryParsable) { }
434434
}
435435

436436
[Theory]
437-
[MemberData(nameof(DelegatesWithInvalidAttributes))]
437+
[MemberData(nameof(DelegatesWithAttributesOnNotTryParsableParameters))]
438438
public void CreateThrowsInvalidOperationExceptionWhenAttributeRequiresTryParseMethodThatDoesNotExist(Delegate action)
439439
{
440440
var ex = Assert.Throws<InvalidOperationException>(() => RequestDelegateFactory.Create(action));
@@ -719,11 +719,13 @@ void TestAction([FromBody] Todo todo)
719719
[Fact]
720720
public void BuildRequestDelegateThrowsInvalidOperationExceptionGivenFromBodyOnMultipleParameters()
721721
{
722-
void TestExplicitlyInvalidAction([FromBody] int value1, [FromBody] int value2) { }
722+
void TestAttributedInvalidAction([FromBody] int value1, [FromBody] int value2) { }
723723
void TestInferredInvalidAction(Todo value1, Todo value2) { }
724+
void TestBothInvalidAction(Todo value1, [FromBody] int value2) { }
724725

725-
Assert.Throws<InvalidOperationException>(() => RequestDelegateFactory.Create((Action<int, int>)TestExplicitlyInvalidAction));
726+
Assert.Throws<InvalidOperationException>(() => RequestDelegateFactory.Create((Action<int, int>)TestAttributedInvalidAction));
726727
Assert.Throws<InvalidOperationException>(() => RequestDelegateFactory.Create((Action<Todo, Todo>)TestInferredInvalidAction));
728+
Assert.Throws<InvalidOperationException>(() => RequestDelegateFactory.Create((Action<Todo, int>)TestBothInvalidAction));
727729
}
728730

729731
public static object[][] FromServiceActions

0 commit comments

Comments
 (0)