// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
///
/// A context that contains operating information for model binding and validation.
///
public class ModelBindingContext
{
private string _fieldName;
private ModelMetadata _modelMetadata;
private string _modelName;
private ModelStateDictionary _modelState;
private OperationBindingContext _operationBindingContext;
private IValueProvider _valueProvider;
///
/// Initializes a new instance of the class.
///
public ModelBindingContext()
{
}
///
/// Creates a new for top-level model binding operation.
///
///
/// The associated with the binding operation.
///
/// associated with the model.
/// associated with the model.
/// The name of the property or parameter being bound.
/// A new instance of .
public static ModelBindingContext CreateBindingContext(
OperationBindingContext operationBindingContext,
ModelStateDictionary modelState,
ModelMetadata metadata,
BindingInfo bindingInfo,
string modelName)
{
if (operationBindingContext == null)
{
throw new ArgumentNullException(nameof(operationBindingContext));
}
if (modelState == null)
{
throw new ArgumentNullException(nameof(modelState));
}
if (metadata == null)
{
throw new ArgumentNullException(nameof(metadata));
}
if (modelName == null)
{
throw new ArgumentNullException(nameof(modelName));
}
var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
var propertyPredicateProvider =
bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider;
return new ModelBindingContext()
{
BinderModelName = binderModelName,
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,
ValidationState = new ValidationStateDictionary(),
};
}
public static ModelBindingContext CreateChildBindingContext(
ModelBindingContext parent,
ModelMetadata modelMetadata,
string fieldName,
string modelName,
object model)
{
if (parent == null)
{
throw new ArgumentNullException(nameof(parent));
}
if (modelMetadata == null)
{
throw new ArgumentNullException(nameof(modelMetadata));
}
if (fieldName == null)
{
throw new ArgumentNullException(nameof(fieldName));
}
if (modelName == null)
{
throw new ArgumentNullException(nameof(modelName));
}
return new ModelBindingContext()
{
ModelState = parent.ModelState,
OperationBindingContext = parent.OperationBindingContext,
ValueProvider = parent.ValueProvider,
ValidationState = parent.ValidationState,
Model = model,
ModelMetadata = modelMetadata,
ModelName = modelName,
FieldName = fieldName,
BinderModelName = modelMetadata.BinderModelName,
BinderType = modelMetadata.BinderType,
BindingSource = modelMetadata.BindingSource,
PropertyFilter = modelMetadata.PropertyBindingPredicateProvider?.PropertyFilter,
};
}
///
/// Represents the associated with this context.
///
public OperationBindingContext OperationBindingContext
{
get { return _operationBindingContext; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_operationBindingContext = value;
}
}
///
/// Gets or sets the name of the current field being bound.
///
public string FieldName
{
get { return _fieldName; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_fieldName = value;
}
}
///
/// Gets or sets the model value for the current operation.
///
///
/// The will typically be set for a binding operation that works
/// against a pre-existing model object to update certain properties.
///
public object Model { get; set; }
///
/// Gets or sets the metadata for the model associated with this context.
///
public ModelMetadata ModelMetadata
{
get { return _modelMetadata; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_modelMetadata = value;
}
}
///
/// Gets or sets the name of the model. This property is used as a key for looking up values in
/// during model binding.
///
public string ModelName
{
get { return _modelName; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_modelName = value;
}
}
///
/// Gets or sets the used to capture values
/// for properties in the object graph of the model when binding.
///
public ModelStateDictionary ModelState
{
get { return _modelState; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_modelState = value;
}
}
///
/// Gets the type of the model.
///
///
/// The property must be set to access this property.
///
public Type ModelType => ModelMetadata?.ModelType;
///
/// Gets or sets a model name which is explicitly set using an .
/// .
///
public string BinderModelName { get; set; }
///
/// Gets or sets a value which represents the associated with the
/// .
///
public BindingSource BindingSource { get; set; }
///
/// Gets the of an associated with the
/// .
///
public Type BinderType { get; set; }
///
/// Gets or sets a value that indicates whether the binder should use an empty prefix to look up
/// values in when no values are found using the prefix.
///
///
/// Passed into the model binding system. Should not be true when is
/// false.
///
public bool FallbackToEmptyPrefix { get; set; }
///
/// Gets or sets an indication that the current binder is handling the top-level object.
///
/// Passed into the model binding system.
public bool IsTopLevelObject { get; set; }
///
/// Gets or sets the associated with this context.
///
public IValueProvider ValueProvider
{
get { return _valueProvider; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_valueProvider = value;
}
}
///
/// Gets or sets a predicate which will be evaluated for each property to determine if the property
/// is eligible for model binding.
///
public Func PropertyFilter { get; set; }
///
/// Gets or sets the . Used for tracking validation state to
/// customize validation behavior for a model object.
///
public ValidationStateDictionary ValidationState { get; set; }
}
}