Skip to content

Commit 0e97421

Browse files
committed
ElementalValueProvider performs incorrect ContainsPrefix check.
1 parent 099a84e commit 0e97421

File tree

11 files changed

+558
-2
lines changed

11 files changed

+558
-2
lines changed

src/Microsoft.Web.Mvc/ElementalValueProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public ElementalValueProvider(string name, object rawValue, CultureInfo culture)
2424

2525
public bool ContainsPrefix(string prefix)
2626
{
27-
return ValueProviderUtil.IsPrefixMatch(Name, prefix);
27+
return ValueProviderUtil.IsPrefixMatch(prefix, Name);
2828
}
2929

3030
public ValueProviderResult GetValue(string key)

src/System.Web.Http/ValueProviders/Providers/ElementalValueProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public ElementalValueProvider(string name, object rawValue, CultureInfo culture)
2222

2323
public bool ContainsPrefix(string prefix)
2424
{
25-
return PrefixContainer.IsPrefixMatch(Name, prefix);
25+
return PrefixContainer.IsPrefixMatch(prefix, Name);
2626
}
2727

2828
public ValueProviderResult GetValue(string key)

test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Globalization;
55
using System.Linq;
66
using System.Web.Http.Controllers;
7+
using System.Web.Http.Metadata;
78
using System.Web.Http.Metadata.Providers;
89
using System.Web.Http.ModelBinding.Binders;
910
using System.Web.Http.Util;
@@ -216,5 +217,118 @@ public void BindSimpleCollection_SubBindingSucceeds()
216217
Assert.Equal(new[] { 42 }, boundCollection.ToArray());
217218
Assert.Equal(new[] { childValidationNode }, bindingContext.ValidationNode.ChildNodes.ToArray());
218219
}
220+
221+
[Fact]
222+
public void BindingUnboundedCollection_WhenNoValuesArePresent_ProducesSingleEntryCollection()
223+
{
224+
// Arrange
225+
string propertyName = "Addresses";
226+
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
227+
modelAccessor: null,
228+
containerType: typeof(UserWithAddress),
229+
propertyName: propertyName);
230+
ModelBindingContext bindingContext = new ModelBindingContext
231+
{
232+
ModelMetadata = modelMetadata,
233+
ModelName = propertyName,
234+
ValueProvider = new SimpleHttpValueProvider { { propertyName, "some value" } }
235+
};
236+
HttpActionContext context = ContextUtil.CreateActionContext();
237+
CollectionModelBinder<UserWithAddress> binder = new CollectionModelBinder<UserWithAddress>();
238+
239+
// Act
240+
bool result = binder.BindModel(context, bindingContext);
241+
242+
// Assert
243+
Assert.True(result);
244+
List<UserWithAddress> boundModel = Assert.IsType<List<UserWithAddress>>(bindingContext.Model);
245+
UserWithAddress listModel = Assert.Single(boundModel);
246+
Assert.Null(listModel.Addresses);
247+
}
248+
249+
[Fact]
250+
public void BindingNestedUnboundedCollection_WhenNoValuesArePresent_ProducesEmptyCollection()
251+
{
252+
// Arrange
253+
string propertyName = "Addresses";
254+
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
255+
modelAccessor: null,
256+
containerType: typeof(UserWithAddress),
257+
propertyName: propertyName);
258+
ModelBindingContext bindingContext = new ModelBindingContext
259+
{
260+
ModelMetadata = modelMetadata,
261+
ModelName = propertyName,
262+
ValueProvider = new SimpleHttpValueProvider { { "Addresses.AddressLines", "some value" } }
263+
};
264+
HttpActionContext context = ContextUtil.CreateActionContext();
265+
CollectionModelBinder<UserWithAddress> binder = new CollectionModelBinder<UserWithAddress>();
266+
267+
// Act
268+
bool result = binder.BindModel(context, bindingContext);
269+
270+
// Assert
271+
Assert.True(result);
272+
List<UserWithAddress> boundModel = Assert.IsType<List<UserWithAddress>>(bindingContext.Model);
273+
Assert.Empty(boundModel);
274+
}
275+
276+
[Fact]
277+
public void BindingListsWithIndex_ProducesSingleLengthCollection_WithNullValues()
278+
{
279+
// Arrange
280+
string propertyName = "Addresses";
281+
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
282+
modelAccessor: null,
283+
containerType: typeof(UserWithAddress),
284+
propertyName: propertyName);
285+
ModelBindingContext bindingContext = new ModelBindingContext
286+
{
287+
ModelMetadata = modelMetadata,
288+
ModelName = propertyName,
289+
ValueProvider = new SimpleHttpValueProvider { { "Addresses.index", "10000" } }
290+
};
291+
HttpActionContext context = ContextUtil.CreateActionContext();
292+
CollectionModelBinder<UserWithAddress> binder = new CollectionModelBinder<UserWithAddress>();
293+
294+
// Act
295+
bool result = binder.BindModel(context, bindingContext);
296+
297+
// Assert
298+
Assert.True(result);
299+
List<UserWithAddress> boundModel = Assert.IsType<List<UserWithAddress>>(bindingContext.Model);
300+
UserWithAddress listModel = Assert.Single(boundModel);
301+
Assert.Null(listModel);
302+
}
303+
304+
[Fact]
305+
public void BindingUnboundedCollection_WithRecursiveRelation_ProducesSingleLengthCollection()
306+
{
307+
// Arrange
308+
string propertyName = "People";
309+
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
310+
modelAccessor: null,
311+
containerType: typeof(PeopleModel),
312+
propertyName: propertyName);
313+
ModelBindingContext bindingContext = new ModelBindingContext
314+
{
315+
ModelMetadata = modelMetadata,
316+
ModelName = propertyName,
317+
ValueProvider = new SimpleHttpValueProvider { { propertyName, "test value" } }
318+
};
319+
HttpActionContext context = ContextUtil.CreateActionContext();
320+
CollectionModelBinder<Person> binder =
321+
new CollectionModelBinder<Person>();
322+
323+
// Act
324+
bool result = binder.BindModel(context, bindingContext);
325+
326+
// Assert
327+
Assert.True(result);
328+
List<Person> boundModel =
329+
Assert.IsType<List<Person>>(bindingContext.Model);
330+
Person type = Assert.Single(boundModel);
331+
Assert.Null(type.Name);
332+
}
219333
}
220334
}

0 commit comments

Comments
 (0)