internal static string CollectionTemplate(HtmlHelper html,
            Html5TemplateHelpers.TemplateHelperDelegate templateHelper,
            object attributes = null)
        {
            object model = html.ViewContext.ViewData.ModelMetadata.Model;
            if(model == null)
            {
                return String.Empty;
            }

            IEnumerable collection = model as IEnumerable;
            if(collection == null)
            {
                throw new InvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        "The Collection template was used with an object of type '{0}', which does not implement System.IEnumerable.",
                        model.GetType().FullName
                        )
                    );
            }

            Type typeInCollection = typeof(string);
            Type genericEnumerableType = Html5TypeHelpers.ExtractGenericInterface(collection.GetType(),
                                                                                  typeof(IEnumerable<>));
            if(genericEnumerableType != null)
            {
                typeInCollection = genericEnumerableType.GetGenericArguments()[0];
            }
            bool typeInCollectionIsNullableValueType = Html5TypeHelpers.IsNullableValueType(typeInCollection);

            string oldPrefix = html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;

            try
            {
                html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = String.Empty;

                string fieldNameBase = oldPrefix;
                StringBuilder result = new StringBuilder();
                int index = 0;

                foreach(object item in collection)
                {
                    Type itemType = typeInCollection;
                    if(item != null && !typeInCollectionIsNullableValueType)
                    {
                        itemType = item.GetType();
                    }
                    ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => item, itemType);
                    string fieldName = String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", fieldNameBase, index++);
                    string output = templateHelper(html,
                                                   metadata,
                                                   fieldName,
                                                   null /* templateName */,
                                                   DataBoundControlMode.ReadOnly,
                                                   null /* additionalViewData */,
                                                   attributes);
                    result.Append(output);
                }

                return result.ToString();
            }
            finally
            {
                html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = oldPrefix;
            }
        }
        internal static string ObjectTemplate(HtmlHelper html,
            Html5TemplateHelpers.TemplateHelperDelegate templateHelper,
            object attributes = null)
        {
            ViewDataDictionary viewData = html.ViewContext.ViewData;
            TemplateInfo templateInfo = viewData.TemplateInfo;
            ModelMetadata modelMetadata = viewData.ModelMetadata;
            StringBuilder builder = new StringBuilder();

            if(modelMetadata.Model == null)
            {
                // DDB #225237
                return modelMetadata.NullDisplayText;
            }

            if(templateInfo.TemplateDepth > 1)
            {
                // DDB #224751
                return modelMetadata.SimpleDisplayText;
            }

            foreach(ModelMetadata propertyMetadata in modelMetadata.Properties.Where(pm => ShouldShow(pm, templateInfo))
                )
            {
                if(!propertyMetadata.HideSurroundingHtml)
                {
                    string label = propertyMetadata.GetDisplayName();
                    if(!String.IsNullOrEmpty(label))
                    {
                        builder.AppendFormat(CultureInfo.InvariantCulture,
                                             "<div class=\"display-label\">{0}</div>",
                                             label);
                        builder.AppendLine();
                    }

                    builder.Append("<div class=\"display-field\">");
                }

                builder.Append(templateHelper(html,
                                              propertyMetadata,
                                              propertyMetadata.PropertyName,
                                              null /* templateName */,
                                              DataBoundControlMode.ReadOnly,
                                              null /* additionalViewData */,
                                              attributes));

                if(!propertyMetadata.HideSurroundingHtml)
                {
                    builder.AppendLine("</div>");
                }
            }

            return builder.ToString();
        }