Beispiel #1
0
        /// <inheritdoc />
        /// <remarks>Does nothing if <see cref="For"/> is <c>null</c>.</remarks>
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (For == null)
            {
                // Regular HTML <select/> element. Just make sure Items wasn't specified.
                if (Items != null)
                {
                    var message = Resources.FormatSelectTagHelper_CannotDetermineContentWhenOnlyItemsSpecified(
                        "<select>",
                        nameof(For).ToLowerInvariant(),
                        nameof(Items).ToLowerInvariant());
                    throw new InvalidOperationException(message);
                }

                // Pass through attribute that is also a well-known HTML attribute.
                if (!string.IsNullOrEmpty(Multiple))
                {
                    output.CopyHtmlAttribute(nameof(Multiple), context);
                }
            }
            else
            {
                // Note null or empty For.Name is allowed because TemplateInfo.HtmlFieldPrefix may be sufficient.
                // IHtmlGenerator will enforce name requirements.
                var metadata = For.Metadata;
                if (metadata == null)
                {
                    throw new InvalidOperationException(Resources.FormatTagHelpers_NoProvidedMetadata(
                                                            "<select>",
                                                            nameof(For).ToLowerInvariant(),
                                                            nameof(IModelMetadataProvider),
                                                            For.Name));
                }

                bool allowMultiple;
                if (string.IsNullOrEmpty(Multiple))
                {
                    // Base allowMultiple on the instance or declared type of the expression.
                    var realModelType = For.Metadata.RealModelType;
                    allowMultiple =
                        typeof(string) != realModelType && typeof(IEnumerable).IsAssignableFrom(realModelType);
                }
                else if (string.Equals(Multiple, "multiple", StringComparison.OrdinalIgnoreCase))
                {
                    allowMultiple = true;

                    // Copy exact attribute name and value the user entered. Must be done prior to any copying from a
                    // TagBuilder. Not done in next case because "true" and "false" aren't valid for the HTML 5
                    // attribute.
                    output.CopyHtmlAttribute(nameof(Multiple), context);
                }
                else if (!bool.TryParse(Multiple.ToLowerInvariant(), out allowMultiple))
                {
                    throw new InvalidOperationException(Resources.FormatTagHelpers_InvalidValue_ThreeAcceptableValues(
                                                            "<select>",
                                                            nameof(Multiple).ToLowerInvariant(),
                                                            Multiple,
                                                            bool.FalseString.ToLowerInvariant(),
                                                            bool.TrueString.ToLowerInvariant(),
                                                            nameof(Multiple).ToLowerInvariant())); // acceptable value (as well as attribute name)
                }

                // Ensure GenerateSelect() _never_ looks anything up in ViewData.
                var items = Items ?? Enumerable.Empty <SelectListItem>();

                var tagBuilder = Generator.GenerateSelect(
                    ViewContext,
                    For.Metadata,
                    optionLabel: null,
                    name: For.Name,
                    selectList: items,
                    allowMultiple: allowMultiple,
                    htmlAttributes: null);

                if (tagBuilder != null)
                {
                    output.SelfClosing = false;
                    output.Merge(tagBuilder);
                }
            }
        }