未验证 ASP.NET MVC5 模型
Posted
技术标签:
【中文标题】未验证 ASP.NET MVC5 模型【英文标题】:ASP.NET MVC5 model not being validated 【发布时间】:2021-09-07 12:21:54 【问题描述】:我在我的模型上使用数据注释进行验证,但是当我测试应用程序时,模型被认为是有效的,即使表单完全是空的。这会导致异常,因为控制器中的注册方法引用了一个不存在的对象(因为如果表单无效,模型不应该被实例化)。
这是我的模特
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-\d4-\d4)|(\d-\d3-\d6)$", 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(@"^\d4-\d4$", 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");
不仅仅是错误信息没有打印在页面上,模型本身也被认为是有效的,即使每个字段都是必需的。
【问题讨论】:
【参考方案1】:ModelState.IsValid 将始终为真,因为 FormCollection 对象没有针对它的验证规则。
您应该重构代码以接受 Client 对象而不是 FormCollection 作为 RegisterClient 方法的参数。这样 - MVC 将自动为您实例化对象并使用属性来验证它。
【讨论】:
谢谢!这似乎可行,但是 MVC 如何知道视图中的哪个字段对应于模型中的相应属性?控制器如何知道应该使用第一个输入字段的值来设置我的模型中的Id
属性?
@Dasph MVC 使用输入 name="" 属性来匹配模型类中相同的属性。所以 将设置属性 FullName 的值。它也会尝试进行类型转换。以上是关于未验证 ASP.NET MVC5 模型的主要内容,如果未能解决你的问题,请参考以下文章
客户端验证在带有 Bootstrap 的 ASP.NET MVC5 中不起作用
ASP.NET Web API 身份验证(Web + 移动)
表单身份验证、ASP.NET MVC 和 WCF RESTful 服务