簡體   English   中英

RadioCutton和DropDownList的MVC服務器端驗證

[英]MVC Server-side Validation of RadioButton and DropDownList

使用ASP.NET Core 2.2 Razor Pages,我正在探索將單選按鈕和下拉列表綁定到頁面模型。

很多人都在詢問客戶端驗證以“讓它工作”。

我的問題是:當我看到這段代碼時。 綁定引擎是否正在進行任何服務器端檢查?

@foreach (var gender in Model.Genders)
{
    <input type="radio" asp-for="Gender" value="@gender" id="Gender@(gender)" /> @gender
}

@Html.DropDownListFor(x => x.Country, new List<SelectListItem>
{
    new SelectListItem() {Text = "Canada", Value="CA"},
    new SelectListItem() {Text = "USA", Value="US"},
    new SelectListItem() {Text = "Mexico", Value="MX"}
})  

什么阻止某人發布性別“bababa”和國家“xxx”,這可能導致我的代碼和數據庫中的未定義行為?

如果上面的代碼正在進行這樣的驗證我會感到驚訝(如果我錯了,請糾正我),我找不到帖子詢問這個,因為每個人都在詢問客戶端驗證。

這里推薦的方法是什么?

服務器端和客戶端驗證很重要,您總是需要實現服務器端驗證,也許您的客戶端驗證可以省略但從不進行服務器端驗證,您發布的代碼不執行任何服務器端驗證

我找到了自己優雅的解決方案,因為我沒有找到任何東西。

有了下面的幫助類,我將用這個聲明我的模型

[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" }
});

在我的頁面上插入單選按鈕和下拉列表

@foreach (var item in Model.Gender.ListItems)
{
    <input type="radio" asp-for="Gender.Value" value="@item.Value" id="Gender@(item.Value)" /><label for="Gender@(item.Value)" style="padding-right:15px;"> @item.Text </label>
}
<span asp-validation-for="Gender" class="text-danger"></span>

@Html.DropDownListFor(x => x.Country.Value, Model.Country.ListItems)
<span asp-validation-for="Country" class="text-danger"></span>

瞧! 驗證在客戶端和服務器端都有效,確保發布的值有效。

當然,可以將“Man”和“Woman”移動到常量中,並可以將國家/地區列表移動到一個單獨的類中,該類為整個應用程序生成一次。

這是InputList助手類。

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace EmergenceGuardian.WebsiteTools.Web
{
    /// <summary>
    /// Represents a list of items to display as radio buttons or drop down list that can be bound to a web page and validated.
    /// </summary>
    [InputListValidation]
    public class InputList
    {
        /// <summary>
        /// Initializes a new instance of InputList with specified list of items that will be used for both the value and text.
        /// </summary>
        /// <param name="values">A list of string values reprenting valid values.</param>
        /// <param name="required">Whether this field is required.</param>
        public InputList(IEnumerable<string> values, bool required = true)
        {
            Required = required;
            foreach (var item in values)
            {
                ListItems.Add(new SelectListItem(item, item));
            }
        }

        /// <summary>
        /// Initializes a new instance of InputList with specified list of SelectListItem objects.
        /// </summary>
        /// <param name="values">A list of SelectListItem objects representing display text and valid values.</param>
        /// <param name="required">Whether this field is required.</param>
        public InputList(IEnumerable<SelectListItem> values, bool required = true)
        {
            Required = required;
            ListItems.AddRange(values);
        }

        /// <summary>
        /// Initializes a new instance of InputList with a NameValueCollection allowing quick collection initializer.
        /// </summary>
        /// <param name="values">The NameValueCollection containing display texts and valid values.</param>
        /// <param name="required">Whether this field is required.</param>
        public InputList(NameValueCollection values, bool required = true)
        {
            Required = required;
            foreach (var key in values.AllKeys)
            {
                ListItems.Add(new SelectListItem(values[key], key));
            }
        }

        /// <summary>
        /// Gets or sets whether this field is required.
        /// </summary>
        public bool Required { get; set; }
        /// <summary>
        /// Gets or sets the list of display text and valid values, used for display and validation.
        /// </summary>
        public List<SelectListItem> ListItems { get; set; } = new List<SelectListItem>();
        /// <summary>
        /// Gets or sets the user input value. This value can be bound to the UI and validated by InputListValidation.
        /// </summary>
        public string Value { get; set; }
    }

    /// <summary>
    /// Validates an InputList class to ensure Value is contained in ListItems.
    /// </summary>
    [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()
        {
        }

        /// <summary>
        /// Validates whether InputList.Value contains a valid value.
        /// </summary>
        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;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM