@@ -167,6 +167,122 @@ static void TestAction([FromForm] Dictionary<string, string> args) { }
167167
168168 // Assert - 2
169169 Assert . Equal ( "Specified argument was out of the range of valid values." , anotherException . Message ) ;
170+ }
171+
172+ [ Fact ]
173+ public async Task SupportsFormMappingWithRecordTypes ( )
174+ {
175+ TodoRecord capturedTodo = default ;
176+ void TestAction ( [ FromForm ] TodoRecord args ) { capturedTodo = args ; } ;
177+ var httpContext = CreateHttpContext ( ) ;
178+ httpContext . Request . Form = new FormCollection ( new Dictionary < string , StringValues >
179+ {
180+ {
181+ "id" , "1"
182+ } ,
183+ {
184+ "name" , "Write tests"
185+ } ,
186+ {
187+ "isCompleted" , "false"
188+ }
189+ } ) ;
190+
191+ var factoryResult = RequestDelegateFactory . Create ( TestAction ) ;
192+ var requestDelegate = factoryResult . RequestDelegate ;
193+
194+ await requestDelegate ( httpContext ) ;
195+
196+ Assert . Equal ( StatusCodes . Status200OK , httpContext . Response . StatusCode ) ;
197+ Assert . Equal ( 1 , capturedTodo . Id ) ;
198+ Assert . Equal ( "Write tests" , capturedTodo . Name ) ;
199+ Assert . False ( capturedTodo . IsCompleted ) ;
200+ }
201+
202+ [ Fact ]
203+ public async Task SupportsRecursiveProperties ( )
204+ {
205+ Employee capturedEmployee = default ;
206+ void TestAction ( [ FromForm ] Employee args ) { capturedEmployee = args ; } ;
207+ var httpContext = CreateHttpContext ( ) ;
208+ httpContext . Request . Form = new FormCollection ( new Dictionary < string , StringValues >
209+ {
210+ {
211+ "Name" , "A"
212+ } ,
213+ {
214+ "Manager.Name" , "B"
215+ } ,
216+ {
217+ "Manager.Manager.Name" , "C"
218+ } ,
219+ {
220+ "Manager.Manager.Manager.Name" , "D"
221+ }
222+ } ) ;
223+
224+ var factoryResult = RequestDelegateFactory . Create ( TestAction ) ;
225+ var requestDelegate = factoryResult . RequestDelegate ;
226+
227+ await requestDelegate ( httpContext ) ;
228+
229+ Assert . Equal ( StatusCodes . Status200OK , httpContext . Response . StatusCode ) ;
230+ }
170231
232+ [ Fact ]
233+ public async Task SupportsRecursivePropertiesWithRecursionLimit ( )
234+ {
235+ Employee capturedEmployee = default ;
236+ var options = new RequestDelegateFactoryOptions
237+ {
238+ EndpointBuilder = CreateEndpointBuilder ( new List < object > ( )
239+ {
240+ new FormMappingOptionsMetadata ( maxRecursionDepth : 3 )
241+ } ) ,
242+ } ;
243+ var metadataResult = new RequestDelegateMetadataResult { EndpointMetadata = new List < object > ( ) } ;
244+ void TestAction ( [ FromForm ] Employee args ) { capturedEmployee = args ; } ;
245+ var httpContext = CreateHttpContext ( ) ;
246+ httpContext . Request . Form = new FormCollection ( new Dictionary < string , StringValues >
247+ {
248+ {
249+ "Name" , "A"
250+ } ,
251+ {
252+ "Manager.Name" , "B"
253+ } ,
254+ {
255+ "Manager.Manager.Name" , "C"
256+ } ,
257+ {
258+ "Manager.Manager.Manager.Name" , "D"
259+ } ,
260+ {
261+ "Manager.Manager.Manager.Manager.Name" , "E"
262+ } ,
263+ {
264+ "Manager.Manager.Manager.Manager.Manager.Name" , "F"
265+ } ,
266+ {
267+ "Manager.Manager.Manager.Manager.Manager.Manager.Name" , "G"
268+ }
269+ } ) ;
270+
271+ var factoryResult = RequestDelegateFactory . Create ( TestAction , options , metadataResult ) ;
272+ var requestDelegate = factoryResult . RequestDelegate ;
273+
274+ var exception = await Assert . ThrowsAsync < FormDataMappingException > ( async ( ) => await requestDelegate ( httpContext ) ) ;
275+
276+ Assert . Equal ( "Manager.Manager.Manager" , exception . Error . Key ) ;
277+ Assert . Equal ( "The maximum recursion depth of '3' was exceeded for 'Manager.Manager.Manager.Name'." , exception . Error . Message . ToString ( CultureInfo . InvariantCulture ) ) ;
278+
279+ }
280+
281+ private record TodoRecord ( int Id , string Name , bool IsCompleted ) ;
282+
283+ private class Employee
284+ {
285+ public string Name { get ; set ; }
286+ public Employee Manager { get ; set ; }
171287 }
172288}
0 commit comments