ASP.NET MVC5 模型未经过验证

ASP.NET MVC5 model not being validated

我在我的模型上使用数据注释进行验证,但是当我测试应用程序时,该模型被认为是有效的,即使表单完全是空的。这会导致异常,因为控制器中的注册方法引用了一个不存在的对象(因为如果表单无效,则不应实例化模型)。

这是我的模型

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MVCExample.Models
{
    public class Client
    {
        [Required(ErrorMessage="ID Cannot be empty.")]
        [RegularExpression(@"^(0\d-\d{4}-\d{4})|(\d-\d{3}-\d{6})$", ErrorMessage ="ID Format is Invalid.")]
        [StringLength(12, ErrorMessage="Length cannot be greater than 12.", MinimumLength = 12)]
        public string Id { get; set; }
        [Required(ErrorMessage = "Name cannot be empty.")]
        [StringLength(60, ErrorMessage = "Name must be between 10 and 60 characters.", MinimumLength = 10)]
        public string FullName { get; set; }
        [Required(ErrorMessage = "Phone number cannot be empty.")]
        [StringLength(9, ErrorMessage = "Phone number must have 9 characters.", MinimumLength = 9)]
        [RegularExpression(@"^\d{4}-\d{4}$", ErrorMessage ="Phone Format is incorrect.")]
        public string PhoneNumber { get; set; }
        [Required(ErrorMessage = "Must choose a discount option.")]
        
        public bool Discount { get; set; }
        [Required(ErrorMessage = "Invalid Amount.")]
        [RegularExpression(@"^\d+$", ErrorMessage ="Value must be a number.")]
        [Range(1, double.MaxValue, ErrorMessage ="Amount must be greater than 0.")]
        public decimal RecentPurchasesAmount { get; set; }
        [Required(ErrorMessage = "Invalid Amount.")]
        [RegularExpression(@"^\d+$", ErrorMessage = "Value must be a number.")]
        [Range(1, double.MaxValue, ErrorMessage ="Amount must be greater than 0.")]
        public decimal LastYearPurchases { get; set; }
        [Required(ErrorMessage = "Invalid Amount.")]
        [RegularExpression(@"^\d+$", ErrorMessage = "Value must be a number.")]
        [Range(1, int.MaxValue, ErrorMessage ="Amount must be greater than 0.")]
        public int AcUnitsPurchased { get; set; }

        public Client() { }

        public Client(string pId, string pName, string pPhone, bool pDisc, decimal pRecentPurchase, decimal pLastYearPurchase, int pUnits)
        {
            this.Id = pId;
            this.FullName = pName;
            this.PhoneNumber = pPhone;
            this.Discount = pDisc;
            this.RecentPurchasesAmount = pRecentPurchase;
            this.LastYearPurchases = pLastYearPurchase;
            this.AcUnitsPurchased = pUnits;

        }
    }
}

cshtml 视图

@model MVCExample.Models.Client

@{
    ViewBag.Title = "Example";
    ViewBag.Message = "Registration";
}

<h1 class="store-title">@ViewBag.Title</h1>
<h2 class="page-title">@ViewBag.Message</h2>
@using (Html.BeginForm("RegisterClient", "AppRegistration"))
{

    @Html.AntiForgeryToken();


    <label for="inp_registryId">Id</label>

    <input type="text" id="inp_registryId" name="Id" />
    //This is never showing up in the browser.
    @Html.ValidationMessageFor(model => model.Id, null, new { @class="text-danger"})

    <label for="inp_registryFullName">Full Name</label>
    <input type="text" id="inp_registryFullName" name="FullName" />

    <label for="inp_registryTelephone">Phone</label>
    <input type="text" id="inp_registryTelephone" name="Phone" />

    <div class="radio-box">
        <p>Client qualifies for discount</p>
        <label for="radioBtn_registryDiscountYes">Yes</label>
        <input type="radio" id="radioBtn_registryDiscountYes" value="true" name="radioBtnDiscount" />

        <label for="radioBtn_registryDiscountNo">No</label>
        <input type="radio" id="radioBtn_registryDiscountNo" value="false" name="radioBtnDiscount" />

    </div>

    <label for="inp_registryRecentPurchases">Amount for recent purchases</label>
    <input type="number" id="inp_registryRecentPurchases" name="RecentPurchases"/>

    <label for="inp_registryLastYearPurchases">Amount for last year purchases</label>
    <input type="number" id="inp_registryLastYearPurchases" name="LastYearPurchases" />

    <label for="inp_registryAcUnitsPurchased">Units purchased</label>
    <input type="number" id="inp_registryAcUnitsPurchased" name="UnitsPurchased" />

    <button type="submit" id="btnRegister">Register</button>

}

正在调用控制器方法

[HttpPost]
        [ValidateAntiForgeryToken]
        
        public ActionResult RegisterClient(FormCollection collection)
        {
            try {
                //This code is executing even if the form is empty.
                if (ModelState.IsValid) { 
                ViewData["Id"] = collection["Id"];
                ViewData["FullName"] = collection["FullName"];
                ViewData["Phone"] = collection["Phone"];
                ViewData["Discount"] = collection["radioBtnDiscount"];
                ViewData["RecentPurchases"] = collection["RecentPurchases"];
                ViewData["LastYearPurchases"] = collection["LastYearPurchases"];
                ViewData["UnitsPurchased"] = collection["UnitsPurchased"];

                string id = ViewData["Id"].ToString();
                string fullName = ViewData["FullName"].ToString();
                string phone = ViewData["Phone"].ToString();
                /*Exceptions happen from this point, since it's trying to reference null values */
                bool discount = Boolean.Parse(ViewData["Discount"].ToString());
                decimal recentPurchases = Decimal.Parse(ViewData["RecentPurchases"].ToString());
                decimal lastYearPurchases = Decimal.Parse(ViewData["LastYearPurchases"].ToString());
                int unitsPurchased = Int32.Parse(ViewData["UnitsPurchased"].ToString());

                registeredClients.Add(new Client(id, fullName, phone, discount, recentPurchases, lastYearPurchases, unitsPurchased));
                    return View("Registration");
                } else
                {
                    Debug.WriteLine("Not registered.");
                    return View();
                }

                
            } catch(Exception ex)
            {
                Debug.WriteLine(ex.StackTrace);
                return View("Registration");
            }
        }

不仅错误消息没有打印在页面上,模型本身也被认为是有效的,即使每个字段都是必需的。

ModelState.IsValid 将始终为真,因为 FormCollection 对象没有针对它的验证规则。

您应该重构代码以接受 Client 对象而不是 FormCollection 作为 RegisterClient 方法的参数。这样 - MVC 将自动为您实例化对象并使用属性来验证它。