// 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; } } }