@@ -13,13 +13,15 @@ namespace Microsoft.AspNetCore.Http.Generators.StaticRouteHandlerModel;
13
13
14
14
internal class EndpointParameter
15
15
{
16
- public EndpointParameter ( IParameterSymbol parameter , WellKnownTypes wellKnownTypes )
16
+ public EndpointParameter ( Endpoint endpoint , IParameterSymbol parameter , WellKnownTypes wellKnownTypes )
17
17
{
18
18
Type = parameter . Type ;
19
19
Name = parameter . Name ;
20
20
Ordinal = parameter . Ordinal ;
21
21
Source = EndpointParameterSource . Unknown ;
22
22
IsOptional = parameter . IsOptional ( ) ;
23
+ IsArray = TryGetArrayElementType ( parameter , out var elementType ) ;
24
+ ElementType = elementType ;
23
25
24
26
if ( parameter . HasAttributeImplementingInterface ( wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_Metadata_IFromRouteMetadata ) , out var fromRouteAttribute ) )
25
27
{
@@ -79,8 +81,8 @@ public EndpointParameter(IParameterSymbol parameter, WellKnownTypes wellKnownTyp
79
81
AssigningCode = specialTypeAssigningCode ;
80
82
}
81
83
else if ( SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_IFormFile ) ) ||
82
- SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_IFormFileCollection ) ) ||
83
- SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_IFormCollection ) ) )
84
+ SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_IFormFileCollection ) ) ||
85
+ SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_AspNetCore_Http_IFormCollection ) ) )
84
86
{
85
87
Source = EndpointParameterSource . Unknown ;
86
88
}
@@ -93,6 +95,15 @@ public EndpointParameter(IParameterSymbol parameter, WellKnownTypes wellKnownTyp
93
95
{
94
96
Source = EndpointParameterSource . RouteOrQuery ;
95
97
}
98
+ else if ( ShouldDisableInferredBodyParameters ( endpoint . HttpMethod ) && IsArray && elementType . SpecialType == SpecialType . System_String )
99
+ {
100
+ Source = EndpointParameterSource . Query ;
101
+ }
102
+ else if ( ShouldDisableInferredBodyParameters ( endpoint . HttpMethod ) && SymbolEqualityComparer . Default . Equals ( parameter . Type , wellKnownTypes . Get ( WellKnownType . Microsoft_Extensions_Primitives_StringValues ) ) )
103
+ {
104
+ Source = EndpointParameterSource . Query ;
105
+ IsStringValues = true ;
106
+ }
96
107
else if ( TryGetParsability ( parameter , wellKnownTypes , out var parsingBlockEmitter ) )
97
108
{
98
109
Source = EndpointParameterSource . RouteOrQuery ;
@@ -105,10 +116,24 @@ public EndpointParameter(IParameterSymbol parameter, WellKnownTypes wellKnownTyp
105
116
}
106
117
}
107
118
119
+ private static bool ShouldDisableInferredBodyParameters ( string httpMethod )
120
+ {
121
+ switch ( httpMethod )
122
+ {
123
+ case "MapPut" or "MapPatch" or "MapPost" :
124
+ return false ;
125
+ default :
126
+ return true ;
127
+ }
128
+ }
129
+
108
130
public ITypeSymbol Type { get ; }
131
+ public ITypeSymbol ElementType { get ; }
132
+
109
133
public string Name { get ; }
110
134
public int Ordinal { get ; }
111
135
public bool IsOptional { get ; }
136
+ public bool IsArray { get ; set ; }
112
137
113
138
public EndpointParameterSource Source { get ; }
114
139
@@ -119,18 +144,33 @@ public EndpointParameter(IParameterSymbol parameter, WellKnownTypes wellKnownTyp
119
144
[ MemberNotNullWhen ( true , nameof ( ParsingBlockEmitter ) ) ]
120
145
public bool IsParsable { get ; }
121
146
public Action < CodeWriter , string , string > ? ParsingBlockEmitter { get ; }
147
+ public bool IsStringValues { get ; }
122
148
123
149
public BindabilityMethod ? BindMethod { get ; }
124
150
125
151
private static bool HasBindAsync ( IParameterSymbol parameter , WellKnownTypes wellKnownTypes , [ NotNullWhen ( true ) ] out BindabilityMethod ? bindMethod )
126
152
{
127
- var parameterType = parameter . Type . UnwrapTypeSymbol ( ) ;
153
+ var parameterType = parameter . Type . UnwrapTypeSymbol ( unwrapArray : true , unwrapNullable : true ) ;
128
154
return ParsabilityHelper . GetBindability ( parameterType , wellKnownTypes , out bindMethod ) == Bindability . Bindable ;
129
155
}
130
156
157
+ private static bool TryGetArrayElementType ( IParameterSymbol parameter , [ NotNullWhen ( true ) ] out ITypeSymbol elementType )
158
+ {
159
+ if ( parameter . Type . TypeKind == TypeKind . Array )
160
+ {
161
+ elementType = parameter . Type . UnwrapTypeSymbol ( unwrapArray : true , unwrapNullable : false ) ;
162
+ return true ;
163
+ }
164
+ else
165
+ {
166
+ elementType = null ! ;
167
+ return false ;
168
+ }
169
+ }
170
+
131
171
private bool TryGetParsability ( IParameterSymbol parameter , WellKnownTypes wellKnownTypes , [ NotNullWhen ( true ) ] out Action < CodeWriter , string , string > ? parsingBlockEmitter )
132
172
{
133
- var parameterType = parameter . Type . UnwrapTypeSymbol ( ) ;
173
+ var parameterType = parameter . Type . UnwrapTypeSymbol ( unwrapArray : true , unwrapNullable : true ) ;
134
174
135
175
// ParsabilityHelper returns a single enumeration with a Parsable/NonParsable enumeration result. We use this already
136
176
// in the analyzers to determine whether we need to warn on whether a type needs to implement TryParse/IParsable<T>. To
@@ -205,10 +245,23 @@ private bool TryGetParsability(IParameterSymbol parameter, WellKnownTypes wellKn
205
245
{
206
246
parsingBlockEmitter = ( writer , inputArgument , outputArgument ) =>
207
247
{
208
- writer . WriteLine ( $$ """ if (!{{ preferredTryParseInvocation ( inputArgument , outputArgument ) }} )""" ) ;
209
- writer . StartBlock ( ) ;
210
- writer . WriteLine ( "wasParamCheckFailure = true;" ) ;
211
- writer . EndBlock ( ) ;
248
+ if ( IsArray && ElementType . NullableAnnotation == NullableAnnotation . Annotated )
249
+ {
250
+ writer . WriteLine ( $$ """ if (!{{ preferredTryParseInvocation ( inputArgument , outputArgument ) }} )""" ) ;
251
+ writer . StartBlock ( ) ;
252
+ writer . WriteLine ( $$ """ if (!string.IsNullOrEmpty({{ inputArgument }} ))""" ) ;
253
+ writer . StartBlock ( ) ;
254
+ writer . WriteLine ( "wasParamCheckFailure = true;" ) ;
255
+ writer . EndBlock ( ) ;
256
+ writer . EndBlock ( ) ;
257
+ }
258
+ else
259
+ {
260
+ writer . WriteLine ( $$ """ if (!{{ preferredTryParseInvocation ( inputArgument , outputArgument ) }} )""" ) ;
261
+ writer . StartBlock ( ) ;
262
+ writer . WriteLine ( "wasParamCheckFailure = true;" ) ;
263
+ writer . EndBlock ( ) ;
264
+ }
212
265
} ;
213
266
}
214
267
0 commit comments