Add FieldName to model binding context

Adds a new property, FieldName, to ModelBindingContext. The FieldName is
the name of whatever code-element is being bound, regardless of what
model-prefix is in use.

This is needed for cases like the Header model binder. We always want to
use the property/parameter name and we don't care about model prefixes.
This commit is contained in:
Ryan Nowak 2015-08-26 18:00:40 -07:00
parent e0e2ff6825
commit dadee80aa8
20 changed files with 179 additions and 239 deletions

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -15,10 +14,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private static readonly Func<ModelBindingContext, string, bool>
_defaultPropertyFilter = (context, propertyName) => true;
private string _modelName;
private ModelStateDictionary _modelState;
private Func<ModelBindingContext, string, bool> _propertyFilter;
/// <summary>
/// Initializes a new instance of the <see cref="ModelBindingContext"/> class.
/// </summary>
@ -27,67 +22,82 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <summary>
/// Constructs a new instance of the <see cref="ModelBindingContext"/> class using the
/// <paramref name="bindingContext" />.
/// Creates a new <see cref="ModelBindingContext"/> for top-level model binding operation.
/// </summary>
/// <param name="bindingContext">Existing <see cref="ModelBindingContext"/>.</param>
/// <param name="modelName">Model name of associated with the new <see cref="ModelBindingContext"/>.</param>
/// <param name="modelMetadata">Model metadata of associated with the new <see cref="ModelBindingContext"/>.
/// <param name="operationBindingContext">
/// The <see cref="OperationBindingContext"/> associated with the binding operation.
/// </param>
public static ModelBindingContext GetChildModelBindingContext(
[NotNull] ModelBindingContext bindingContext,
[NotNull] string modelName,
[NotNull] ModelMetadata modelMetadata)
{
var modelBindingContext = new ModelBindingContext
{
ModelName = modelName,
ModelMetadata = modelMetadata,
ModelState = bindingContext.ModelState,
ValueProvider = bindingContext.ValueProvider,
OperationBindingContext = bindingContext.OperationBindingContext,
BindingSource = modelMetadata.BindingSource,
BinderModelName = modelMetadata.BinderModelName,
BinderType = modelMetadata.BinderType,
};
return modelBindingContext;
}
/// <summary>
/// Constructs a new instance of <see cref="ModelBindingContext"/> from given <paramref name="metadata"/>
/// and <paramref name="bindingInfo"/>.
/// </summary>
/// <param name="metadata"><see cref="ModelMetadata"/> associated with the model.</param>
/// <param name="bindingInfo"><see cref="BindingInfo"/> associated with the model.</param>
/// <param name="modelName">An optional name of the model to be used.</param>
/// <param name="modelName">The name of the property or parameter being bound.</param>
/// <returns>A new instance of <see cref="ModelBindingContext"/>.</returns>
public static ModelBindingContext GetModelBindingContext(
public static ModelBindingContext CreateBindingContext(
[NotNull] OperationBindingContext operationBindingContext,
[NotNull] ModelStateDictionary modelState,
[NotNull] ModelMetadata metadata,
BindingInfo bindingInfo,
string modelName)
[NotNull] string modelName)
{
var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
var propertyPredicateProvider =
bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider;
return new ModelBindingContext
return new ModelBindingContext()
{
ModelMetadata = metadata,
BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource,
PropertyFilter = propertyPredicateProvider?.PropertyFilter,
BinderType = bindingInfo?.BinderType ?? metadata.BinderType,
BinderModelName = binderModelName,
ModelName = binderModelName ?? metadata.PropertyName ?? modelName,
BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource,
BinderType = bindingInfo?.BinderType ?? metadata.BinderType,
PropertyFilter = propertyPredicateProvider?.PropertyFilter,
// We only support fallback to empty prefix in cases where the model name is inferred from
// the parameter or property being bound.
FallbackToEmptyPrefix = binderModelName == null,
// Because this is the top-level context, FieldName and ModelName should be the same.
FieldName = binderModelName ?? modelName,
ModelName = binderModelName ?? modelName,
IsTopLevelObject = true,
ModelMetadata = metadata,
ModelState = modelState,
OperationBindingContext = operationBindingContext,
ValueProvider = operationBindingContext.ValueProvider,
};
}
public static ModelBindingContext CreateChildBindingContext(
[NotNull] ModelBindingContext parent,
[NotNull] ModelMetadata modelMetadata,
[NotNull] string fieldName,
[NotNull] string modelName,
object model)
{
return new ModelBindingContext()
{
ModelState = parent.ModelState,
OperationBindingContext = parent.OperationBindingContext,
ValueProvider = parent.ValueProvider,
Model = model,
ModelMetadata = modelMetadata,
ModelName = modelName,
FieldName = fieldName,
BinderModelName = modelMetadata.BinderModelName,
BinderType = modelMetadata.BinderType,
BindingSource = modelMetadata.BindingSource,
PropertyFilter = modelMetadata.PropertyBindingPredicateProvider?.PropertyFilter,
};
}
/// <summary>
/// Represents the <see cref="OperationBindingContext"/> associated with this context.
/// </summary>
public OperationBindingContext OperationBindingContext { get; set; }
public OperationBindingContext OperationBindingContext { get; [param:NotNull] set; }
/// <summary>
/// Gets or sets the name of the current field being bound.
/// </summary>
public string FieldName { get; [param: NotNull] set; }
/// <summary>
/// Gets or sets the model value for the current operation.
@ -101,41 +111,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// <summary>
/// Gets or sets the metadata for the model associated with this context.
/// </summary>
public ModelMetadata ModelMetadata { get; set; }
public ModelMetadata ModelMetadata { get; [param: NotNull] set; }
/// <summary>
/// Gets or sets the name of the model. This property is used as a key for looking up values in
/// <see cref="IValueProvider"/> during model binding.
/// </summary>
public string ModelName
{
get
{
if (_modelName == null)
{
_modelName = string.Empty;
}
return _modelName;
}
set { _modelName = value; }
}
public string ModelName { get; [param: NotNull] set; }
/// <summary>
/// Gets or sets the <see cref="ModelStateDictionary"/> used to capture <see cref="ModelState"/> values
/// for properties in the object graph of the model when binding.
/// </summary>
public ModelStateDictionary ModelState
{
get
{
if (_modelState == null)
{
_modelState = new ModelStateDictionary();
}
return _modelState;
}
set { _modelState = value; }
}
public ModelStateDictionary ModelState { get; [param: NotNull] set; }
/// <summary>
/// Gets the type of the model.
@ -143,14 +131,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// <remarks>
/// The <see cref="ModelMetadata"/> property must be set to access this property.
/// </remarks>
public Type ModelType
{
get
{
EnsureModelMetadata();
return ModelMetadata.ModelType;
}
}
public Type ModelType => ModelMetadata?.ModelType;
/// <summary>
/// Gets or sets a model name which is explicitly set using an <see cref="IModelNameProvider"/>.
@ -202,27 +183,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// <summary>
/// Gets or sets the <see cref="IValueProvider"/> associated with this context.
/// </summary>
public IValueProvider ValueProvider { get; set; }
public IValueProvider ValueProvider { get; [param: NotNull] set; }
public Func<ModelBindingContext, string, bool> PropertyFilter
{
get
{
if (_propertyFilter == null)
{
_propertyFilter = _defaultPropertyFilter;
}
return _propertyFilter;
}
set { _propertyFilter = value; }
}
private void EnsureModelMetadata()
{
if (ModelMetadata == null)
{
throw new InvalidOperationException(Resources.ModelBindingContext_ModelMetadataMustBeSet);
}
}
/// <summary>
/// Gets or sets a predicate which will be evaluated for each property to determine if the property
/// is eligible for model binding.
/// </summary>
public Func<ModelBindingContext, string, bool> PropertyFilter { get; set; }
}
}
}

View File

@ -73,12 +73,12 @@ namespace Microsoft.AspNet.Mvc
[NotNull] OperationBindingContext operationContext)
{
var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
var modelBindingContext = GetModelBindingContext(
parameter.Name,
var modelBindingContext = ModelBindingContext.CreateBindingContext(
operationContext,
modelState,
metadata,
parameter.BindingInfo,
modelState,
operationContext);
parameter.Name);
var modelBindingResult = await operationContext.ModelBinder.BindModelAsync(modelBindingContext);
if (modelBindingResult != null &&
@ -187,26 +187,6 @@ namespace Microsoft.AspNet.Mvc
}
}
private static ModelBindingContext GetModelBindingContext(
string parameterName,
ModelMetadata metadata,
BindingInfo bindingInfo,
ModelStateDictionary modelState,
OperationBindingContext operationBindingContext)
{
var modelBindingContext = ModelBindingContext.GetModelBindingContext(
metadata,
bindingInfo,
parameterName);
modelBindingContext.IsTopLevelObject = true;
modelBindingContext.ModelState = modelState;
modelBindingContext.ValueProvider = operationBindingContext.ValueProvider;
modelBindingContext.OperationBindingContext = operationBindingContext;
return modelBindingContext;
}
private OperationBindingContext GetOperationBindingContext(
ActionContext actionContext,
ActionBindingContext bindingContext)

View File

@ -149,12 +149,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
bindingContext.ModelMetadata,
boundCollection);
var innerBindingContext = ModelBindingContext.CreateChildBindingContext(
bindingContext,
elementMetadata,
fieldName: bindingContext.FieldName,
modelName: bindingContext.ModelName,
model: null);
foreach (var value in values)
{
var innerBindingContext = ModelBindingContext.GetChildModelBindingContext(
bindingContext,
bindingContext.ModelName,
elementMetadata);
innerBindingContext.ValueProvider = new CompositeValueProvider
{
// our temporary provider goes at the front of the list
@ -222,10 +226,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
foreach (var indexName in indexNames)
{
var fullChildName = ModelNames.CreateIndexModelName(bindingContext.ModelName, indexName);
var childBindingContext = ModelBindingContext.GetChildModelBindingContext(
var childBindingContext = ModelBindingContext.CreateChildBindingContext(
bindingContext,
fullChildName,
elementMetadata);
elementMetadata,
fieldName: indexName,
modelName: fullChildName,
model: null);
var didBind = false;
object boundValue = null;

View File

@ -148,6 +148,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Model = oldBindingContext.Model,
ModelMetadata = oldBindingContext.ModelMetadata,
ModelName = modelName,
FieldName = oldBindingContext.FieldName,
ModelState = oldBindingContext.ModelState,
ValueProvider = oldBindingContext.ValueProvider,
OperationBindingContext = oldBindingContext.OperationBindingContext,

View File

@ -57,10 +57,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Update the existing successful but empty ModelBindingResult.
var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
var valueMetadata = metadataProvider.GetMetadataForType(typeof(TValue));
var valueBindingContext = ModelBindingContext.GetChildModelBindingContext(
var valueBindingContext = ModelBindingContext.CreateChildBindingContext(
bindingContext,
bindingContext.ModelName,
valueMetadata);
valueMetadata,
fieldName: bindingContext.FieldName,
modelName: bindingContext.ModelName,
model: null);
var modelBinder = bindingContext.OperationBindingContext.ModelBinder;
var validationNode = result.ValidationNode;

View File

@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var modelMetadata = bindingContext.ModelMetadata;
// Property name can be null if the model metadata represents a type (rather than a property or parameter).
var headerName = bindingContext.BinderModelName ?? modelMetadata.PropertyName ?? bindingContext.ModelName;
var headerName = bindingContext.FieldName;
object model = null;
if (bindingContext.ModelType == typeof(string))
{

View File

@ -93,11 +93,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
parentBindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(typeof(TModel));
var propertyModelName =
ModelNames.CreatePropertyModelName(parentBindingContext.ModelName, propertyName);
var propertyBindingContext = ModelBindingContext.GetChildModelBindingContext(
var propertyBindingContext = ModelBindingContext.CreateChildBindingContext(
parentBindingContext,
propertyModelMetadata,
propertyName,
propertyModelName,
propertyModelMetadata);
propertyBindingContext.BinderModelName = propertyModelMetadata.BinderModelName;
model: null);
var modelBindingResult = await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync(
propertyBindingContext);

View File

@ -160,14 +160,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
isAnyPropertyEnabledForValueProviderBasedBinding = true;
var propertyModelName = ModelNames.CreatePropertyModelName(
var fieldName = propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName;
var modelName = ModelNames.CreatePropertyModelName(
context.ModelBindingContext.ModelName,
propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName);
fieldName);
var propertyModelBindingContext = ModelBindingContext.GetChildModelBindingContext(
var propertyModelBindingContext = ModelBindingContext.CreateChildBindingContext(
context.ModelBindingContext,
propertyModelName,
propertyMetadata);
propertyMetadata,
fieldName: fieldName,
modelName: modelName,
model: null);
// If any property can return a true value.
if (CanBindValue(propertyModelBindingContext))
@ -274,31 +277,34 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var results = new Dictionary<ModelMetadata, ModelBindingResult>();
foreach (var propertyMetadata in propertyMetadatas)
{
var propertyModelName = ModelNames.CreatePropertyModelName(
bindingContext.ModelName,
propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName);
var childContext = ModelBindingContext.GetChildModelBindingContext(
bindingContext,
propertyModelName,
propertyMetadata);
// ModelBindingContext.Model property values may be non-null when invoked via TryUpdateModel(). Pass
// complex (including collection) values down so that binding system does not unnecessarily recreate
// instances or overwrite inner properties that are not bound. No need for this with simple values
// because they will be overwritten if binding succeeds. Arrays are never reused because they cannot
// be resized.
object model = null;
if (propertyMetadata.PropertyGetter != null &&
propertyMetadata.IsComplexType &&
!propertyMetadata.ModelType.IsArray)
{
childContext.Model = propertyMetadata.PropertyGetter(bindingContext.Model);
model = propertyMetadata.PropertyGetter(bindingContext.Model);
}
var result = await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(childContext);
var fieldName = propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName;
var modelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, fieldName);
var propertyContext = ModelBindingContext.CreateChildBindingContext(
bindingContext,
propertyMetadata,
fieldName: fieldName,
modelName: modelName,
model: model);
var result = await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyContext);
if (result == null)
{
// Could not bind. Let ProcessResult() know explicitly.
result = new ModelBindingResult(model: null, key: propertyModelName, isModelSet: false);
result = new ModelBindingResult(model: null, key: propertyContext.ModelName, isModelSet: false);
}
results[propertyMetadata] = result;
@ -359,7 +365,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var modelMetadataPredicate = context.ModelMetadata.PropertyBindingPredicateProvider?.PropertyFilter;
return
context.PropertyFilter(context, propertyName) &&
(context.PropertyFilter == null || context.PropertyFilter(context, propertyName)) &&
(modelMetadataPredicate == null || modelMetadataPredicate(context, propertyName));
};
}

View File

@ -293,21 +293,18 @@ namespace Microsoft.AspNet.Mvc
ModelBinder = modelBinder,
ValidatorProvider = validatorProvider,
MetadataProvider = metadataProvider,
HttpContext = httpContext
HttpContext = httpContext,
ValueProvider = valueProvider,
};
var modelBindingContext = new ModelBindingContext
{
Model = model,
ModelMetadata = modelMetadata,
ModelName = prefix,
ModelState = modelState,
ValueProvider = valueProvider,
FallbackToEmptyPrefix = true,
IsTopLevelObject = true,
OperationBindingContext = operationBindingContext,
PropertyFilter = predicate,
};
var modelBindingContext = ModelBindingContext.CreateBindingContext(
operationBindingContext,
modelState,
modelMetadata,
bindingInfo: null,
modelName: prefix ?? string.Empty);
modelBindingContext.Model = model;
modelBindingContext.PropertyFilter = predicate;
var modelBindingResult = await modelBinder.BindModelAsync(modelBindingContext);
if (modelBindingResult != null && modelBindingResult.IsModelSet)

View File

@ -222,11 +222,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = modelMetadata,
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{
ModelBinder = CreateIntBinder(),
MetadataProvider = metadataProvider
MetadataProvider = metadataProvider,
},
};
return bindingContext;

View File

@ -129,10 +129,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = metadataProvider.GetMetadataForType(modelType),
ModelName = "foo",
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{
MetadataProvider = metadataProvider
MetadataProvider = metadataProvider,
}
};
return bindingContext;

View File

@ -419,6 +419,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = metadataProvider.GetMetadataForType(typeof(IList<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{

View File

@ -24,14 +24,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var mockIntBinder = new Mock<IModelBinder>();
@ -71,14 +68,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var mockIntBinder = new Mock<IModelBinder>();
@ -121,14 +115,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var modelBinder = new Mock<IModelBinder>();
@ -155,14 +146,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var count = 0;
@ -201,14 +189,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var modelBinder = new Mock<IModelBinder>();
@ -238,14 +223,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var modelBinder = new Mock<IModelBinder>();
@ -276,14 +258,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
OperationBindingContext = new OperationBindingContext
{
ValidatorProvider = GetValidatorProvider()
}
};
var modelBinder = new Mock<IModelBinder>();
@ -318,6 +297,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
FallbackToEmptyPrefix = false,
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelState = new ModelStateDictionary(),
};
// Act
@ -341,7 +321,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
FallbackToEmptyPrefix = true,
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(int)),
ModelState = new ModelStateDictionary(),
OperationBindingContext = Mock.Of<OperationBindingContext>(),
OperationBindingContext = new OperationBindingContext(),
};
// Act
@ -504,24 +484,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Same(validationNode, result.ValidationNode);
}
private static ModelBindingContext CreateBindingContext(IModelBinder binder,
IValueProvider valueProvider,
Type type,
IModelValidatorProvider validatorProvider = null)
private static ModelBindingContext CreateBindingContext(
IModelBinder binder,
IValueProvider valueProvider,
Type type)
{
validatorProvider = validatorProvider ?? GetValidatorProvider();
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
var bindingContext = new ModelBindingContext
{
FallbackToEmptyPrefix = true,
ModelMetadata = metadataProvider.GetMetadataForType(type),
ModelName = "parameter",
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{
MetadataProvider = metadataProvider,
ModelBinder = binder,
ValidatorProvider = validatorProvider
}
};
return bindingContext;
@ -547,26 +526,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
return shimBinder;
}
private static IModelValidatorProvider GetValidatorProvider(params IModelValidator[] validators)
{
var provider = new Mock<IModelValidatorProvider>();
provider
.Setup(v => v.GetValidators(It.IsAny<ModelValidatorProviderContext>()))
.Callback<ModelValidatorProviderContext>(c =>
{
if (validators == null)
{
return;
}
foreach (var validator in validators)
{
c.Validators.Add(validator);
}
});
return provider.Object;
}
private class SimplePropertiesModel
{

View File

@ -429,6 +429,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
var modelBindingContext = new ModelBindingContext()
{
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext()
{
HttpContext = new DefaultHttpContext(),
@ -510,6 +511,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = metadataProvider.GetMetadataForType(typeof(IDictionary<int, string>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
ModelBinder = binder.Object,

View File

@ -159,6 +159,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
ModelMetadata = metadataProvider.GetMetadataForType(modelType),
ModelName = "file",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
ModelBinder = new FormFileModelBinder(),

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new HeaderModelBinder();
var modelBindingContext = GetBindingContext(type);
modelBindingContext.ModelName = header;
modelBindingContext.FieldName = header;
modelBindingContext.OperationBindingContext.HttpContext.Request.Headers.Add(header, new[] { headerValue });
// Act
@ -61,7 +61,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new HeaderModelBinder();
var modelBindingContext = GetBindingContext(type);
modelBindingContext.ModelName = header;
modelBindingContext.FieldName = header;
modelBindingContext.OperationBindingContext.HttpContext.Request.Headers.Add(header, new[] { headerValue });
// Act
@ -81,6 +81,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = modelMetadata,
ModelName = "modelName",
FieldName = "modelName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
ModelBinder = new HeaderModelBinder(),

View File

@ -255,6 +255,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = metataProvider.GetMetadataForType(keyValuePairType ?? typeof(KeyValuePair<int, string>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{

View File

@ -10,14 +10,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class ModelBindingContextTest
{
[Fact]
public void GetChildModelBindingContext()
public void CreateChildBindingContext_CopiesProperties()
{
// Arrange
var originalBindingContext = new ModelBindingContext
{
Model = new object(),
ModelMetadata = new TestModelMetadataProvider().GetMetadataForType(typeof(object)),
ModelName = "theName",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext(),
ValueProvider = new SimpleValueProvider()
};
@ -32,19 +33,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var newModelMetadata = metadataProvider.GetMetadataForType(typeof(object));
// Act
var newBindingContext = ModelBindingContext.GetChildModelBindingContext(
var newBindingContext = ModelBindingContext.CreateChildBindingContext(
originalBindingContext,
string.Empty,
newModelMetadata);
newModelMetadata,
fieldName: "fieldName",
modelName: "modelprefix.fieldName",
model: null);
// Assert
Assert.Same(newModelMetadata, newBindingContext.ModelMetadata);
Assert.Same(newModelMetadata.BindingSource, newBindingContext.BindingSource);
Assert.Same(newModelMetadata.BinderModelName, newBindingContext.BinderModelName);
Assert.Same(newModelMetadata.BinderType, newBindingContext.BinderType);
Assert.Equal("", newBindingContext.ModelName);
Assert.Equal(originalBindingContext.ModelState, newBindingContext.ModelState);
Assert.Equal(originalBindingContext.ValueProvider, newBindingContext.ValueProvider);
Assert.Same(newModelMetadata.BindingSource, newBindingContext.BindingSource);
Assert.False(newBindingContext.FallbackToEmptyPrefix);
Assert.Equal("fieldName", newBindingContext.FieldName);
Assert.False(newBindingContext.IsFirstChanceBinding);
Assert.False(newBindingContext.IsTopLevelObject);
Assert.Null(newBindingContext.Model);
Assert.Same(newModelMetadata, newBindingContext.ModelMetadata);
Assert.Equal("modelprefix.fieldName", newBindingContext.ModelName);
Assert.Same(originalBindingContext.ModelState, newBindingContext.ModelState);
Assert.Same(originalBindingContext.OperationBindingContext, newBindingContext.OperationBindingContext);
Assert.Same(originalBindingContext.ValueProvider, newBindingContext.ValueProvider);
}
[Fact]

View File

@ -796,6 +796,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Model = model,
ModelMetadata = containerMetadata,
ModelName = "theModel",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),
@ -846,6 +847,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Model = model,
ModelMetadata = containerMetadata,
ModelName = "theModel",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),
@ -1649,9 +1651,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return new ModelBindingContext
{
Model = model,
ModelState = new ModelStateDictionary(),
ModelMetadata = metadata,
ModelName = "theModel",
ModelState = new ModelStateDictionary(),
OperationBindingContext = new OperationBindingContext
{
MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),

View File

@ -185,6 +185,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType),
ModelName = "theModelName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleValueProvider() // empty
};
}