public void DefaultValues() { // Arrange var provider = new Mock<IModelMetadataProvider>(); // Act var metadata = new ModelMetadata(provider.Object, typeof(Exception), () => "model", typeof(string), "propertyName"); // Assert Assert.Equal(typeof(Exception), metadata.ContainerType); Assert.True(metadata.ConvertEmptyStringToNull); Assert.False(metadata.IsComplexType); Assert.False(metadata.IsReadOnly); Assert.False(metadata.IsRequired); Assert.Null(metadata.Description); Assert.Null(metadata.DisplayFormatString); Assert.Null(metadata.DisplayName); Assert.Null(metadata.EditFormatString); Assert.Null(metadata.NullDisplayText); Assert.Null(metadata.TemplateHint); Assert.Equal("model", metadata.Model); Assert.Equal("model", metadata.SimpleDisplayText); Assert.Equal(typeof(string), metadata.ModelType); Assert.Equal("propertyName", metadata.PropertyName); }
public void LabelHelpers_ReturnEmptyForModel_IfMetadataPropertyNameEmpty() { // Arrange var metadata = new ModelMetadata( new DataAnnotationsModelMetadataProvider(), containerType: null, modelAccessor: null, modelType: typeof(object), propertyName: string.Empty); var helper = DefaultTemplatesUtilities.GetHtmlHelper(); helper.ViewData.ModelMetadata = metadata; // Act var labelResult = helper.Label(""); var labelNullResult = helper.Label(expression: null); // null is another alias for current model var labelForResult = helper.LabelFor(m => m); var labelForModelResult = helper.LabelForModel(); // Assert Assert.Empty(labelResult.ToString()); Assert.Empty(labelNullResult.ToString()); Assert.Empty(labelForResult.ToString()); Assert.Empty(labelForModelResult.ToString()); }
/// <summary> /// Creates a new instance of <see cref="InputFormatterContext"/>. /// </summary> /// <param name="httpContext"> /// The <see cref="Http.HttpContext"/> for the current operation. /// </param> /// <param name="modelName">The name of the model.</param> /// <param name="modelState"> /// The <see cref="ModelStateDictionary"/> for recording errors. /// </param> /// <param name="modelType"> /// The <see cref="Type"/> of the model to deserialize. /// </param> public InputFormatterContext( HttpContext httpContext, string modelName, ModelStateDictionary modelState, ModelMetadata metadata) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (modelName == null) { throw new ArgumentNullException(nameof(modelName)); } if (modelState == null) { throw new ArgumentNullException(nameof(modelState)); } if (metadata == null) { throw new ArgumentNullException(nameof(metadata)); } HttpContext = httpContext; ModelName = modelName; ModelState = modelState; Metadata = metadata; ModelType = metadata.ModelType; }
private IEnumerable<IModelValidator> GetValidatorsForType(ModelMetadata metadata) { var attributes = metadata.ModelType .GetTypeInfo() .GetCustomAttributes(); return GetValidators(metadata, attributes); }
/// <summary> /// Creates a new <see cref="ModelExplorer"/>. /// </summary> /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param> /// <param name="container">The container <see cref="ModelExplorer"/>.</param> /// <param name="metadata">The <see cref="ModelMetadata"/>.</param> /// <param name="modelAccessor">A model accessor function. May be <c>null</c>.</param> public ModelExplorer( IModelMetadataProvider metadataProvider, ModelExplorer container, ModelMetadata metadata, Func<object, object> modelAccessor) { if (metadataProvider == null) { throw new ArgumentNullException(nameof(metadataProvider)); } if (container == null) { throw new ArgumentNullException(nameof(container)); } if (metadata == null) { throw new ArgumentNullException(nameof(metadata)); } _metadataProvider = metadataProvider; Container = container; Metadata = metadata; _modelAccessor = modelAccessor; }
/// <summary> /// Creates a new <see cref="ModelBindingContext"/> for top-level model binding operation. /// </summary> /// <param name="operationBindingContext"> /// The <see cref="OperationBindingContext"/> associated with the binding operation. /// </param> /// <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">The name of the property or parameter being bound.</param> /// <returns>A new instance of <see cref="ModelBindingContext"/>.</returns> 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 void IsComplexTypeTestsReturnsTrueForComplexTypes(Type type) { // Arrange var provider = new Mock<IModelMetadataProvider>(); // Act var modelMetadata = new ModelMetadata(provider.Object, null, null, type, null); // Assert Assert.True(modelMetadata.IsComplexType); }
public ErrorsOrderer(ModelMetadata metadata) { if (metadata == null) { throw new ArgumentNullException(nameof(metadata)); } foreach (var data in metadata.Properties) { _ordering[data.PropertyName] = data.Order; } }
public ModelValidationContext([NotNull] IModelMetadataProvider metadataProvider, [NotNull] IEnumerable<IModelValidatorProvider> validatorProviders, [NotNull] ModelStateDictionary modelState, [NotNull] ModelMetadata metadata, ModelMetadata containerMetadata) { ModelMetadata = metadata; ModelState = modelState; MetadataProvider = metadataProvider; ValidatorProviders = validatorProviders; ContainerMetadata = containerMetadata; }
public TableColumn(ModelMetadata meta) : this() { Id = meta.PropertyName; For = meta.PropertyName; Order = meta.Order; Title = meta.DisplayName ?? meta.PropertyName.SplitCamelCase(); CellDisplayFormat = meta.DisplayFormatString; CellNullDisplayText = meta.NullDisplayText; CellUihint = meta.TemplateHint; CellVisible = !meta.HideSurroundingHtml; }
public TemplateBuilder( IViewEngine viewEngine, IViewBufferScope bufferScope, ViewContext viewContext, ViewDataDictionary viewData, ModelExplorer modelExplorer, string htmlFieldName, string templateName, bool readOnly, object additionalViewData) { if (viewEngine == null) { throw new ArgumentNullException(nameof(viewEngine)); } if (bufferScope == null) { throw new ArgumentNullException(nameof(_bufferScope)); } if (viewContext == null) { throw new ArgumentNullException(nameof(viewContext)); } if (viewData == null) { throw new ArgumentNullException(nameof(viewData)); } if (modelExplorer == null) { throw new ArgumentNullException(nameof(modelExplorer)); } _viewEngine = viewEngine; _bufferScope = bufferScope; _viewContext = viewContext; _viewData = viewData; _modelExplorer = modelExplorer; _htmlFieldName = htmlFieldName; _templateName = templateName; _readOnly = readOnly; _additionalViewData = additionalViewData; _model = modelExplorer.Model; _metadata = modelExplorer.Metadata; }
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes) { if (metadata.ContainerType == null || string.IsNullOrEmpty(metadata.PropertyName)) { // Validate that the type's fields and nonpublic properties don't have any validation attributes on // them. Validation only runs against public properties var type = metadata.ModelType; var nonPublicProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance); foreach (var nonPublicProperty in nonPublicProperties) { if (nonPublicProperty.GetCustomAttributes(typeof(ValidationAttribute), inherit: true).Any()) { var message = Resources.FormatValidationAttributeOnNonPublicProperty(nonPublicProperty.Name, type); yield return new ErrorModelValidator(message); } } var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var allFields = metadata.ModelType.GetFields(bindingFlags); foreach (var field in allFields) { if (field.GetCustomAttributes(typeof(ValidationAttribute), inherit: true).Any()) { var message = Resources.FormatValidationAttributeOnField(field.Name, type); yield return new ErrorModelValidator(message); } } } else { // Validate that value-typed properties marked as [Required] are also marked as // [DataMember(IsRequired=true)]. Certain formatters may not recognize a member as required if it's // marked as [Required] but not [DataMember(IsRequired=true)]. This is not a problem for reference // types because [Required] will still cause a model error to be raised after a null value is // deserialized. if (metadata.ModelType.GetTypeInfo().IsValueType && attributes.Any(attribute => attribute is RequiredAttribute)) { if (!DataMemberModelValidatorProvider.IsRequiredDataMember(metadata.ContainerType, attributes)) { var message = Resources.FormatMissingDataMemberIsRequired(metadata.PropertyName, metadata.ContainerType); yield return new ErrorModelValidator(message); } } } }
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes) { // Types cannot be required; only properties can if (metadata.ContainerType == null || string.IsNullOrEmpty(metadata.PropertyName)) { return Enumerable.Empty<IModelValidator>(); } if (IsRequiredDataMember(metadata.ContainerType, attributes)) { return new[] { new RequiredMemberModelValidator() }; } return Enumerable.Empty<IModelValidator>(); }
public TemplateBuilder([NotNull] IViewEngine viewEngine, [NotNull] ViewContext viewContext, [NotNull] ViewDataDictionary viewData, [NotNull] ModelMetadata metadata, string htmlFieldName, string templateName, bool readOnly, object additionalViewData) { _viewEngine = viewEngine; _viewContext = viewContext; _viewData = viewData; _metadata = metadata; _htmlFieldName = htmlFieldName; _templateName = templateName; _readOnly = readOnly; _additionalViewData = additionalViewData; }
/// <summary> /// Creates a new <see cref="ModelExplorer"/>. /// </summary> /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param> /// <param name="metadata">The <see cref="ModelMetadata"/>.</param> /// <param name="model">The model object. May be <c>null</c>.</param> public ModelExplorer( IModelMetadataProvider metadataProvider, ModelMetadata metadata, object model) { if (metadataProvider == null) { throw new ArgumentNullException(nameof(metadataProvider)); } if (metadata == null) { throw new ArgumentNullException(nameof(metadata)); } _metadataProvider = metadataProvider; Metadata = metadata; _model = model; }
private IEnumerable<IModelValidator> GetValidatorsForProperty(ModelMetadata metadata) { var propertyName = metadata.PropertyName; var bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase; var property = metadata.ContainerType .GetProperty(propertyName, bindingFlags); if (property == null) { throw new ArgumentException( Resources.FormatCommon_PropertyNotFound( metadata.ContainerType.FullName, metadata.PropertyName), "metadata"); } var attributes = property.GetCustomAttributes(); return GetValidators(metadata, attributes); }
/// <summary> /// Creates a new instance of <see cref="InputFormatterContext"/>. /// </summary> /// <param name="httpContext"> /// The <see cref="Http.HttpContext"/> for the current operation. /// </param> /// <param name="modelName">The name of the model.</param> /// <param name="modelState"> /// The <see cref="ModelStateDictionary"/> for recording errors. /// </param> /// <param name="metadata"> /// The <see cref="ModelMetadata"/> of the model to deserialize. /// </param> /// <param name="readerFactory"> /// A delegate which can create a <see cref="TextReader"/> for the request body. /// </param> public InputFormatterContext( HttpContext httpContext, string modelName, ModelStateDictionary modelState, ModelMetadata metadata, Func<Stream, Encoding, TextReader> readerFactory) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (modelName == null) { throw new ArgumentNullException(nameof(modelName)); } if (modelState == null) { throw new ArgumentNullException(nameof(modelState)); } if (metadata == null) { throw new ArgumentNullException(nameof(metadata)); } if (readerFactory == null) { throw new ArgumentNullException(nameof(readerFactory)); } HttpContext = httpContext; ModelName = modelName; ModelState = modelState; Metadata = metadata; ReaderFactory = readerFactory; ModelType = metadata.ModelType; }
public void ValidateSetsMemberNamePropertyOfValidationContextForProperties(ModelMetadata metadata, string expectedMemberName) { // Arrange var attribute = new Mock<ValidationAttribute> { CallBase = true }; attribute.Protected() .Setup<ValidationResult>("IsValid", ItExpr.IsAny<object>(), ItExpr.IsAny<ValidationContext>()) .Callback((object o, ValidationContext context) => { Assert.Equal(expectedMemberName, context.MemberName); }) .Returns(ValidationResult.Success) .Verifiable(); var validator = new DataAnnotationsModelValidator(attribute.Object); var validationContext = CreateValidationContext(metadata); // Act var results = validator.Validate(validationContext); // Assert Assert.Empty(results); attribute.VerifyAll(); }
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes) { var results = new List<IModelValidator>(); // Produce a validator for each validation attribute we find foreach (var attribute in attributes.OfType<ValidationAttribute>()) { DataAnnotationsModelValidationFactory factory; if (!_attributeFactories.TryGetValue(attribute.GetType(), out factory)) { factory = _defaultAttributeFactory; } results.Add(factory(attribute)); } // Produce a validator if the type supports IValidatableObject if (typeof(IValidatableObject).IsAssignableFrom(metadata.ModelType)) { results.Add(_defaultValidatableFactory()); } return results; }
public static IEnumerable<string> GetTypeNames(ModelMetadata modelMetadata, Type fieldType) { // Not returning type name here for IEnumerable<IFormFile> since we will be returning // a more specific name, IEnumerableOfIFormFileName. var fieldTypeInfo = fieldType.GetTypeInfo(); if (typeof(IEnumerable<IFormFile>) != fieldType) { yield return fieldType.Name; } if (fieldType == typeof(string)) { // Nothing more to provide yield break; } else if (!modelMetadata.IsComplexType) { // IsEnum is false for the Enum class itself if (fieldTypeInfo.IsEnum) { // Same as fieldType.BaseType.Name in this case yield return "Enum"; } else if (fieldType == typeof(DateTimeOffset)) { yield return "DateTime"; } yield return "String"; yield break; } else if (!fieldTypeInfo.IsInterface) { var type = fieldType; while (true) { type = type.GetTypeInfo().BaseType; if (type == null || type == typeof(object)) { break; } yield return type.Name; } } if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(fieldTypeInfo)) { if (typeof(IEnumerable<IFormFile>).GetTypeInfo().IsAssignableFrom(fieldTypeInfo)) { yield return IEnumerableOfIFormFileName; // Specific name has already been returned, now return the generic name. if (typeof(IEnumerable<IFormFile>) == fieldType) { yield return fieldType.Name; } } yield return "Collection"; } else if (typeof(IFormFile) != fieldType && typeof(IFormFile).GetTypeInfo().IsAssignableFrom(fieldTypeInfo)) { yield return nameof(IFormFile); } yield return "Object"; }
protected override IEnumerable<SelectListItem> GetEnumSelectList(ModelMetadata metadata) { Metadata = metadata; SelectListItems = base.GetEnumSelectList(metadata); if (SelectListItems != null) { // Perform a deep copy to help confirm the mutable items are not changed. var copiedSelectListItems = new List<SelectListItem>(); CopiedSelectListItems = copiedSelectListItems; foreach (var item in SelectListItems) { var copy = new SelectListItem { Disabled = item.Disabled, Group = item.Group, Selected = item.Selected, Text = item.Text, Value = item.Value, }; copiedSelectListItems.Add(copy); } } return SelectListItems; }
public abstract IEnumerable<IModelValidator> AbstractGetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes);
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes) { return AbstractGetValidators(metadata, attributes); }
public new void SetProperty( ModelBindingContext bindingContext, ModelExplorer modelExplorer, ModelMetadata propertyMetadata, ModelBindingResult result) { base.SetProperty(bindingContext, modelExplorer, propertyMetadata, result); }
protected override bool CanUpdateProperty(ModelMetadata propertyMetadata) { return CanUpdatePropertyPublic(propertyMetadata); }
private static ModelBindingContext CreateContext(ModelMetadata metadata, object model) { return new ModelBindingContext { Model = model, ModelState = new ModelStateDictionary(), ModelMetadata = metadata, ModelName = "theModel", OperationBindingContext = new OperationBindingContext { MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), ValidatorProvider = TestModelValidatorProvider.CreateDefaultProvider(), } }; }
internal static bool CanUpdatePropertyInternal(ModelMetadata propertyMetadata) { return(!propertyMetadata.IsReadOnly || CanUpdateReadOnlyProperty(propertyMetadata.ModelType)); }
private static ModelValidationContext CreateValidationContext(ModelMetadata metadata) { return(new ModelValidationContext(null, null, null, metadata, null)); }
private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo) { return metadata.ShowForDisplay && !metadata.IsComplexType && !templateInfo.Visited(metadata); }
// Called when the property setter null check failed, allows us to add our own error message to ModelState. internal static EventHandler <ModelValidatedEventArgs> CreateNullCheckFailedHandler(ModelMetadata modelMetadata, object incomingValue) { return((sender, e) => { var validationNode = (ModelValidationNode)sender; var modelState = e.ValidationContext.ModelState; var validationState = modelState.GetFieldValidationState(validationNode.ModelStateKey); if (validationState == ModelValidationState.Unvalidated) { // TODO: https://github.com/aspnet/Mvc/issues/450 Revive ModelBinderConfig // var errorMessage = ModelBinderConfig.ValueRequiredErrorMessageProvider(e.ValidationContext, // modelMetadata, // incomingValue); var errorMessage = Resources.ModelBinderConfig_ValueRequired; if (errorMessage != null) { modelState.TryAddModelError(validationNode.ModelStateKey, errorMessage); } } }); }
protected virtual void SetProperty(ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, IModelValidator requiredValidator) { var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase; var property = bindingContext.ModelType .GetProperty(propertyMetadata.PropertyName, bindingFlags); if (property == null || !property.CanWrite) { // nothing to do return; } object value; var hasDefaultValue = false; if (dtoResult.IsModelBound) { value = dtoResult.Model; } else { hasDefaultValue = TryGetPropertyDefaultValue(property, out value); } propertyMetadata.Model = value; // 'Required' validators need to run first so that we can provide useful error messages if // the property setters throw, e.g. if we're setting entity keys to null. if (value == null) { var modelStateKey = dtoResult.ValidationNode.ModelStateKey; var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey); if (validationState == ModelValidationState.Unvalidated) { if (requiredValidator != null) { var validationContext = new ModelValidationContext(bindingContext, propertyMetadata); foreach (var validationResult in requiredValidator.Validate(validationContext)) { bindingContext.ModelState.TryAddModelError(modelStateKey, validationResult.Message); } } } } if (!dtoResult.IsModelBound && !hasDefaultValue) { // If we don't have a value, don't set it on the model and trounce a pre-initialized // value. return; } if (value != null || property.PropertyType.AllowsNullValue()) { try { property.SetValue(bindingContext.Model, value); } catch (Exception ex) { // don't display a duplicate error message if a binding error has already occurred for this field var targetInvocationException = ex as TargetInvocationException; if (targetInvocationException != null && targetInvocationException.InnerException != null) { ex = targetInvocationException.InnerException; } var modelStateKey = dtoResult.ValidationNode.ModelStateKey; var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey); if (validationState == ModelValidationState.Unvalidated) { bindingContext.ModelState.AddModelError(modelStateKey, ex); } } } else { // trying to set a non-nullable value type to null, need to make sure there's a message var modelStateKey = dtoResult.ValidationNode.ModelStateKey; var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey); if (validationState == ModelValidationState.Unvalidated) { dtoResult.ValidationNode.Validated += CreateNullCheckFailedHandler(propertyMetadata, value); } } }
private ModelMetadata GetPathMetadata(ModelMetadata metadata, string path) { var index = 0; while (index >= 0 && index < path.Length) { if (path[index] == '[') { // At start of "[0]". if (metadata.ElementMetadata == null) { // Odd case but don't throw just because ErrorContext had an odd-looking path. break; } metadata = metadata.ElementMetadata; index = path.IndexOf(']', index); } else if (path[index] == '.' || path[index] == ']') { // Skip '.' in "prefix.property" or "[0].property" or ']' in "[0]". index++; } else { // At start of "property", "property." or "property[0]". var endIndex = path.IndexOfAny(new[] { '.', '[' }, index); if (endIndex == -1) { endIndex = path.Length; } var propertyName = path.Substring(index, endIndex - index); if (metadata.Properties[propertyName] == null) { // Odd case but don't throw just because ErrorContext had an odd-looking path. break; } metadata = metadata.Properties[propertyName]; index = endIndex; } } return metadata; }
public virtual bool CanUpdatePropertyPublic(ModelMetadata propertyMetadata) { return base.CanUpdateProperty(propertyMetadata); }
protected abstract IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<Attribute> attributes);
protected virtual bool CanUpdateProperty(ModelMetadata propertyMetadata) { return(CanUpdatePropertyInternal(propertyMetadata)); }