// 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 System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
///
/// A metadata representation of a model type, property or parameter.
///
public abstract class ModelMetadata
{
private bool? _isComplexType;
///
/// The default value of .
///
public static readonly int DefaultOrder = 10000;
///
/// Creates a new .
///
/// The .
protected ModelMetadata([NotNull] ModelMetadataIdentity identity)
{
Identity = identity;
}
///
/// Gets the container type of this metadata if it represents a property, otherwise null .
///
public Type ContainerType { get { return Identity.ContainerType; } }
///
/// Gets a value indicating the kind of metadata element represented by the current instance.
///
public ModelMetadataKind MetadataKind { get { return Identity.MetadataKind; } }
///
/// Gets the model type represented by the current instance.
///
public Type ModelType { get { return Identity.ModelType; } }
///
/// Gets the property name represented by the current instance.
///
public string PropertyName
{
get
{
return Identity.Name;
}
}
///
/// Gets the key for the current instance.
///
protected ModelMetadataIdentity Identity { get; }
///
/// Gets a collection of additional information about the model.
///
public abstract IReadOnlyDictionary AdditionalValues { get; }
///
/// Gets the collection of instances for the model's properties.
///
public abstract ModelPropertyCollection Properties { get; }
///
/// Gets the name of a model if specified explicitly using .
///
public abstract string BinderModelName { get; }
///
/// Gets the of an of a model if specified explicitly using
/// .
///
public abstract Type BinderType { get; }
///
/// Gets a binder metadata for this model.
///
public abstract BindingSource BindingSource { get; }
///
/// Gets a value indicating whether or not to convert an empty string value to null when
/// representing a model as text.
///
public abstract bool ConvertEmptyStringToNull { get; }
///
/// Gets the name of the model's datatype. Overrides in some
/// display scenarios.
///
/// null unless set manually or through additional metadata e.g. attributes.
public abstract string DataTypeName { get; }
///
/// Gets the description of the model.
///
public abstract string Description { get; }
///
/// Gets the composite format (see
/// http://msdn.microsoft.com/en-us/library/txafckwd.aspx) used to display the model.
///
public abstract string DisplayFormatString { get; }
///
/// Gets the display name of the model.
///
public abstract string DisplayName { get; }
///
/// Gets the composite format (see
/// http://msdn.microsoft.com/en-us/library/txafckwd.aspx) used to edit the model.
///
public abstract string EditFormatString { get; }
///
/// Gets the for elements of if that
/// implements .
///
///
/// for T if implements
/// . for object if
/// implements but not . null otherwise i.e. when
/// is false .
///
public abstract ModelMetadata ElementMetadata { get; }
///
/// Gets the ordered display names and values of all values in
/// .
///
///
/// An of mappings between field names
/// and values. null if is false .
///
public abstract IEnumerable> EnumDisplayNamesAndValues { get; }
///
/// Gets the names and values of all values in .
///
///
/// An of mappings between field names
/// and values. null if is false .
///
public abstract IReadOnlyDictionary EnumNamesAndValues { get; }
///
/// Gets a value indicating whether has a non-null , non-empty
/// value different from the default for the datatype.
///
public abstract bool HasNonDefaultEditFormat { get; }
///
/// Gets a value indicating whether the value should be HTML-encoded.
///
/// If true , value should be HTML-encoded. Default is true .
public abstract bool HtmlEncode { get; }
///
/// Gets a value indicating whether the "HiddenInput" display template should return
/// string.Empty (not the expression value) and whether the "HiddenInput" editor template should not
/// also return the expression value (together with the hidden <input> element).
///
///
/// If true , also causes the default display and editor templates to return HTML
/// lacking the usual per-property <div> wrapper around the associated property. Thus the default
/// display template effectively skips the property and the default
/// editor template returns only the hidden <input> element for the property.
///
public abstract bool HideSurroundingHtml { get; }
///
/// Gets a value indicating whether or not the model value can be bound by model binding. This is only
/// applicable when the current instance represents a property.
///
///
/// If true then the model value is considered supported by model binding and can be set
/// based on provided input in the request.
///
public abstract bool IsBindingAllowed { get; }
///
/// Gets a value indicating whether or not the model value is required by model binding. This is only
/// applicable when the current instance represents a property.
///
///
/// If true then the model value is considered required by model binding and must have a value
/// supplied in the request to be considered valid.
///
public abstract bool IsBindingRequired { get; }
///
/// Gets a value indicating whether is for an .
///
///
/// true if type.IsEnum (type.GetTypeInfo().IsEnum for DNX Core 5.0) is true for
/// ; false otherwise.
///
public abstract bool IsEnum { get; }
///
/// Gets a value indicating whether is for an with an
/// associated .
///
///
/// true if is true and has an
/// associated ; false otherwise.
///
public abstract bool IsFlagsEnum { get; }
///
/// Gets a value indicating whether or not the model value is read-only. This is only applicable when
/// the current instance represents a property.
///
public abstract bool IsReadOnly { get; }
///
/// Gets a value indicating whether or not the model value is required. This is only applicable when
/// the current instance represents a property.
///
///
///
/// If true then the model value is considered required by validators.
///
///
/// By default an implicit System.ComponentModel.DataAnnotations.RequiredAttribute will be added
/// if not present when true. .
///
///
public abstract bool IsRequired { get; }
///
/// Gets a value indicating where the current metadata should be ordered relative to other properties
/// in its containing type.
///
///
/// For example this property is used to order items in .
/// The default order is 10000 .
///
/// The order value of the current metadata.
public abstract int Order { get; }
///
/// Gets the text to display when the model is null .
///
public abstract string NullDisplayText { get; }
///
/// Gets the , which can determine which properties
/// should be model bound.
///
public abstract IPropertyBindingPredicateProvider PropertyBindingPredicateProvider { get; }
///
/// Gets a value that indicates whether the property should be displayed in read-only views.
///
public abstract bool ShowForDisplay { get; }
///
/// Gets a value that indicates whether the property should be displayed in editable views.
///
public abstract bool ShowForEdit { get; }
///
/// Gets a value which is the name of the property used to display the model.
///
public abstract string SimpleDisplayProperty { get; }
///
/// Gets a string used by the templating system to discover display-templates and editor-templates.
///
public abstract string TemplateHint { get; }
///
/// Gets a collection of metadata items for validators.
///
public abstract IReadOnlyList ValidatorMetadata { get; }
///
/// Gets a value indicating whether is a simple type.
///
///
/// A simple type is defined as a which has a
/// that can convert from .
///
public bool IsComplexType
{
get
{
if (_isComplexType == null)
{
_isComplexType = !TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string));
}
return _isComplexType.Value;
}
}
///
/// Gets a value indicating whether or not is a .
///
public bool IsNullableValueType
{
get
{
return Nullable.GetUnderlyingType(ModelType) != null;
}
}
///
/// Gets a value indicating whether or not is a collection type.
///
///
/// A collection type is defined as a which is assignable to
/// , and is not a .
///
public bool IsCollectionType
{
get
{
if (ModelType == typeof(string))
{
// Even though string implements IEnumerable, we don't really think of it
// as a collection for the purposes of model binding.
return false;
}
// We only need to look for IEnumerable, because IEnumerable extends it.
return typeof(IEnumerable).IsAssignableFrom(ModelType);
}
}
///
/// Gets a value indicating whether or not allows null values.
///
public bool IsReferenceOrNullableType
{
get
{
return !ModelType.GetTypeInfo().IsValueType || IsNullableValueType;
}
}
///
/// Gets the underlying type argument if inherits from .
/// Otherwise gets .
///
///
/// Identical to unless is true .
///
public Type UnderlyingOrModelType
{
get
{
return Nullable.GetUnderlyingType(ModelType) ?? ModelType;
}
}
///
/// Gets a property getter delegate to get the property value from a model object.
///
public abstract Func PropertyGetter { get; }
///
/// Gets a property setter delegate to set the property value on a model object.
///
public abstract Action PropertySetter { get; }
///
/// Gets a display name for the model.
///
///
/// will return the first of the following expressions which has a
/// non-null value: DisplayName , PropertyName , ModelType.Name .
///
/// The display name.
public string GetDisplayName()
{
return DisplayName ?? PropertyName ?? ModelType.Name;
}
}
}