MVC Server-side Validation of RadioButton and DropDownList

前端 未结 2 1284
遇见更好的自我
遇见更好的自我 2021-01-28 13:24

Using ASP.NET Core 2.2 Razor Pages, I\'m exploring binding radio buttons and dropdownlists to the page model.

Plenty of people are asking about client-side validation to

2条回答
  •  时光说笑
    2021-01-28 13:49

    Came up with my own elegant solution since I found nothing out there.

    With the helper class below, I'll declare my model with this

    [BindProperty]
    public InputList Gender { get; set; } = new InputList(new[] { "Man", "Woman" });
    
    [BindProperty]
    public InputList Country { get; set; } = new InputList(new NameValueCollection()
    {
        { "", "--Select--" },
        { "CA", "Canada" },
        { "US", "USA" },
        { "MX", "Mexico" }
    });
    

    Insert radio buttons and a dropdown list on my page

    @foreach (var item in Model.Gender.ListItems)
    {
        
    }
    
    
    @Html.DropDownListFor(x => x.Country.Value, Model.Country.ListItems)
    
    

    And voilà! Validation works both on the client-side and server-side, ensuring posted value is valid.

    Of course, can move "Man" and "Woman" into constants, and can move the list of countries into a separate class that generates it once for the whole application.

    Here's the InputList helper class.

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel.DataAnnotations;
    using Microsoft.AspNetCore.Mvc.Rendering;
    
    namespace EmergenceGuardian.WebsiteTools.Web
    {
        /// 
        /// Represents a list of items to display as radio buttons or drop down list that can be bound to a web page and validated.
        /// 
        [InputListValidation]
        public class InputList
        {
            /// 
            /// Initializes a new instance of InputList with specified list of items that will be used for both the value and text.
            /// 
            /// A list of string values reprenting valid values.
            /// Whether this field is required.
            public InputList(IEnumerable values, bool required = true)
            {
                Required = required;
                foreach (var item in values)
                {
                    ListItems.Add(new SelectListItem(item, item));
                }
            }
    
            /// 
            /// Initializes a new instance of InputList with specified list of SelectListItem objects.
            /// 
            /// A list of SelectListItem objects representing display text and valid values.
            /// Whether this field is required.
            public InputList(IEnumerable values, bool required = true)
            {
                Required = required;
                ListItems.AddRange(values);
            }
    
            /// 
            /// Initializes a new instance of InputList with a NameValueCollection allowing quick collection initializer.
            /// 
            /// The NameValueCollection containing display texts and valid values.
            /// Whether this field is required.
            public InputList(NameValueCollection values, bool required = true)
            {
                Required = required;
                foreach (var key in values.AllKeys)
                {
                    ListItems.Add(new SelectListItem(values[key], key));
                }
            }
    
            /// 
            /// Gets or sets whether this field is required.
            /// 
            public bool Required { get; set; }
            /// 
            /// Gets or sets the list of display text and valid values, used for display and validation.
            /// 
            public List ListItems { get; set; } = new List();
            /// 
            /// Gets or sets the user input value. This value can be bound to the UI and validated by InputListValidation.
            /// 
            public string Value { get; set; }
        }
    
        /// 
        /// Validates an InputList class to ensure Value is contained in ListItems.
        /// 
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
        sealed public class InputListValidationAttribute : ValidationAttribute
        {
            private const string DefaultErrorMessage = "Selected value is invalid.";
            private const string DefaultRequiredErrorMessage = "The {0} field is required.";
    
            public InputListValidationAttribute()
            {
            }
    
            /// 
            /// Validates whether InputList.Value contains a valid value.
            /// 
            protected override ValidationResult IsValid(object value, ValidationContext validationContext)
            {
                var input = value as InputList;
                if (input != null)
                {
                    if (string.IsNullOrEmpty(input.Value))
                    {
                        if (input.Required)
                        {
                            return new ValidationResult(string.Format(ErrorMessage ?? DefaultRequiredErrorMessage, validationContext.MemberName));
                        }
                    }
                    else if (input.ListItems?.Any(x => x.Value == input.Value) == false)
                    {
                        return new ValidationResult(ErrorMessage ?? DefaultErrorMessage);
                    }
    
                }
                return ValidationResult.Success;
            }
        }
    }
    

提交回复
热议问题