Example #1
0
        /// <summary>
        /// Gets <see cref="ModelExplorer"/> for named <paramref name="expression"/> in given
        /// <paramref name="viewData"/>.
        /// </summary>
        /// <param name="expression">Expression name, relative to <c>viewData.Model</c>.</param>
        /// <param name="viewData">
        /// The <see cref="ViewDataDictionary"/> that may contain the <paramref name="expression"/> value.
        /// </param>
        /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
        /// <returns>
        /// <see cref="ModelExplorer"/> for named <paramref name="expression"/> in given <paramref name="viewData"/>.
        /// </returns>
        public static ModelExplorer FromStringExpression(
            string expression,
            [NotNull] ViewDataDictionary viewData,
            IModelMetadataProvider metadataProvider)
        {
            var viewDataInfo = ViewDataEvaluator.Eval(viewData, expression);

            if (viewDataInfo == null)
            {
                // Try getting a property from ModelMetadata if we couldn't find an answer in ViewData
                var propertyExplorer = viewData.ModelExplorer.GetExplorerForProperty(expression);
                if (propertyExplorer != null)
                {
                    return(propertyExplorer);
                }
            }

            if (viewDataInfo != null)
            {
                if (viewDataInfo.Container == viewData &&
                    viewDataInfo.Value == viewData.Model &&
                    string.IsNullOrEmpty(expression))
                {
                    // Nothing for empty expression in ViewData and ViewDataEvaluator just returned the model. Handle
                    // using FromModel() for its object special case.
                    return(FromModel(viewData, metadataProvider));
                }

                ModelExplorer containerExplorer = viewData.ModelExplorer;
                if (viewDataInfo.Container != null)
                {
                    containerExplorer = metadataProvider.GetModelExplorerForType(
                        viewDataInfo.Container.GetType(),
                        viewDataInfo.Container);
                }

                if (viewDataInfo.PropertyInfo != null)
                {
                    // We've identified a property access, which provides us with accurate metadata.
                    var containerType     = viewDataInfo.Container?.GetType() ?? viewDataInfo.PropertyInfo.DeclaringType;
                    var containerMetadata = metadataProvider.GetMetadataForType(viewDataInfo.Container.GetType());
                    var propertyMetadata  = containerMetadata.Properties[viewDataInfo.PropertyInfo.Name];

                    Func <object, object> modelAccessor = (ignore) => viewDataInfo.Value;
                    return(containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor));
                }
                else if (viewDataInfo.Value != null)
                {
                    // We have a value, even though we may not know where it came from.
                    var valueMetadata = metadataProvider.GetMetadataForType(viewDataInfo.Value.GetType());
                    return(containerExplorer.GetExplorerForExpression(valueMetadata, viewDataInfo.Value));
                }
            }

            // Treat the expression as string if we don't find anything better.
            var stringMetadata = metadataProvider.GetMetadataForType(typeof(string));

            return(viewData.ModelExplorer.GetExplorerForExpression(stringMetadata, modelAccessor: null));
        }
Example #2
0
        public static ModelMetadata FromStringExpression(string expression,
                                                         [NotNull] ViewDataDictionary viewData,
                                                         IModelMetadataProvider metadataProvider)
        {
            if (string.IsNullOrEmpty(expression))
            {
                // Empty string really means "ModelMetadata for the current model".
                return(FromModel(viewData, metadataProvider));
            }

            var           viewDataInfo  = ViewDataEvaluator.Eval(viewData, expression);
            Type          containerType = null;
            Type          modelType     = null;
            Func <object> modelAccessor = null;
            string        propertyName  = null;
            object        container     = null;

            if (viewDataInfo != null)
            {
                if (viewDataInfo.Container != null)
                {
                    containerType = viewDataInfo.Container.GetType();
                    container     = viewDataInfo.Container;
                }

                modelAccessor = () => viewDataInfo.Value;

                if (viewDataInfo.PropertyInfo != null)
                {
                    propertyName = viewDataInfo.PropertyInfo.Name;
                    modelType    = viewDataInfo.PropertyInfo.PropertyType;
                }
                else if (viewDataInfo.Value != null)
                {
                    // We only need to delay accessing properties (for LINQ to SQL)
                    modelType = viewDataInfo.Value.GetType();
                }
            }
            else
            {
                //  Try getting a property from ModelMetadata if we couldn't find an answer in ViewData
                var propertyMetadata =
                    viewData.ModelMetadata.Properties.Where(p => p.PropertyName == expression).FirstOrDefault();
                if (propertyMetadata != null)
                {
                    return(propertyMetadata);
                }
            }

            return(GetMetadataFromProvider(modelAccessor,
                                           modelType ?? typeof(string),
                                           propertyName,
                                           container,
                                           containerType,
                                           metadataProvider));
        }