ASP .Net MVC:Razor 视图忽略或跳过验证 ViewBag
ASP .Net MVC: Razor view ignores or skips validation ViewBag
我正在尝试验证我的搜索选项字段,该字段位于 Index.cshtml :
中
当我输入名称时,它工作正常并显示 DetailsBySurname.cshtml 中的所有匹配结果:
这是DetailsBySurname.cshtml
这个 Razor 视图应该根据 ViewBag 内部的内容显示验证成功或错误消息,但是当它从 Controller IActionResult 重定向到我的 Razor 视图并在 ViewBag 中显示错误消息时,它会跳过(我认为)代码块if 语句并直接进入 foreach 循环,该循环应该仅在没有错误消息时才被激活。然后我得到这个错误:
这是 Razor 视图的代码 DetailsBySurname.cshtml:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "DetailsBySurname";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@if (ViewBag.Message != null)
{
<p class="alert-@(ViewBag.Error != null ? "danger" : "success")">@(ViewBag.Message)</p>
if (ViewBag.Error != null)
{
<ul>
@foreach (Exception e in ViewBag.Exception.ValidationExceptions)
{
<li class="alert-danger">@(e.Message)</li>
}
</ul>
}
}
<h1>Details</h1>
<div>
<h4>Employee</h4>
<hr />
@foreach (var item in Model)
{
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.FirstName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.FirstName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => item.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.LastName)
</dd>
</dl>
}
</div>
这是控制器中用于 IAction 结果的代码块 DetailsBySurname:
public async Task<IActionResult> DetailsBySurname(string lastName)
{
if (Request.Query.Count > 0)
{
try
{
ValidationException exception = new ValidationException();
lastName = !string.IsNullOrWhiteSpace(lastName) ? lastName.Trim() : null;
using (CompanyContext context = new CompanyContext())
{
if (string.IsNullOrWhiteSpace(lastName))
{
exception.ValidationExceptions.Add(new Exception("Last Name Not Provided"));
}
// Category ID fails parse.
// Common validation points (5) and (5a).
int n;
bool isNumeric = int.TryParse(lastName, out n);
if (isNumeric)
{
exception.ValidationExceptions.Add(new Exception("ID Not Valid string"));
}
else
{
// Category ID exists.
// Common validation point (7).
if (!context.Employees.Any(x => x.LastName == lastName))
{
exception.ValidationExceptions.Add(new Exception("Last Name Does Not Exist"));
}
}
if (exception.ValidationExceptions.Count > 0)
{
throw exception;
}
}
var employees = _context.Employees.Where(m => m.LastName == lastName);
ViewBag.Message = $"Successfully Found {lastName}!";
return View(employees);
}
// Catch ONLY ValidationException here.
catch (ValidationException e)
{
ViewBag.LastName = lastName;
ViewBag.Message = "There exist problem(s) with your submission, see below.";
ViewBag.Exception = e;
ViewBag.Error = true;
return View(e);
}
}
return View();
}
最后是 Index.cshtml 视图中搜索字段的代码:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
</li>
<li class="nav-item dropdown">
<form action="/Employee/Index" method="get">
<lable for="filter"> Show Laid of Staff</lable>
<input type="checkbox" id="filter" name="filter" value="laidoff" />
<input class="btn btn-outline-success my-2 my-sm-0" type="submit" value="Go!" />
</form>
</li>
</ul>
<form action="/Employee/DetailsByEmail" method="get" class="form-inline my-2 my-lg-0">
<input id="email" name="email" data-val="true" data-val-required="Email is required" class="form-control mr-sm-2" type="search" placeholder="Search by Email" aria-label="Search">
<span class="field-validation-valid" data-valmsg-for="email" data-valmsg-replace="true"></span>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
<form action="/Employee/DetailsBySurname" method="get" class="form-inline my-2 my-lg-0">
<input id="lastName" name="lastName" data-val="true" data-val-required="Last Name is required" class="form-control mr-sm-2" type="search" placeholder="Search by Last Name" aria-label="Search">
<span class="field-validation-valid" data-valmsg-for="lastName" data-valmsg-replace="true"></span>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
我看到调试一直按预期进行,直到最后,只有当它跳转到 Razor View 时,它才会给我上面提到的这个错误。
我还创建了 Class 来处理所有验证异常,但它工作正常。我确定问题出在 Controller 和 Razor 视图之间。或者可能是其他地方的问题,我是 ASP .Net MVC 的新手,有什么建议吗?
我用不同的验证方法修复了它。
对于 DetailsBySurname 我删除了 if(ViewBag... 并添加了不同的 if(ViewData... - 语句来检查返回的结果是否为 null 然后不要 运行 foreach 循环). 要捕获错误消息,请使用另一个 if 语句 @if(!ViewData.ModelState.IsValid) ,如下所示:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "DetailsBySurname";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Details</h1>
<div>
@if (ViewData.ModelState.IsValid)
{
<h4>Employee</h4>
<hr />
@foreach (var item in Model)
{
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.FirstName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.FirstName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.LastName)
</dl>
}
}
</div>
<div class="form-row">
<div class="form-group col-md-2">
@if (!ViewData.ModelState.IsValid)
{
<span class="field-validation-error">@ViewData.ModelState["LastName"].Errors[0].ErrorMessage</span>
}
</div>
</div>
然后在 IAction 结果 DetailsBySurname 的控制器中,我将验证方法更改为内置验证,如下所示:
public async Task<IActionResult> DetailsBySurname(string lastName)
{
lastName = !string.IsNullOrWhiteSpace(lastName) ? lastName.Trim() : null;
if (string.IsNullOrWhiteSpace(lastName))
{
ModelState.AddModelError("LastName", "Last Name not Provided");
//exception.ValidationExceptions.Add(new Exception("Last Name Not Provided"));
}
bool exists;
if (!(exists = _context.Employees.Any(m => m.LastName == lastName)))
{
//return NotFound(new Exception("Email not found"));
ModelState.AddModelError("LastName", "Last Name not found");
}
if (!ModelState.IsValid)
{
return View();
}
else
{
var employee = _context.Employees.Where(m => m.LastName == lastName);
return View(employee);
}
}
我正在尝试验证我的搜索选项字段,该字段位于 Index.cshtml :
中当我输入名称时,它工作正常并显示 DetailsBySurname.cshtml 中的所有匹配结果:
这是DetailsBySurname.cshtml
这个 Razor 视图应该根据 ViewBag 内部的内容显示验证成功或错误消息,但是当它从 Controller IActionResult 重定向到我的 Razor 视图并在 ViewBag 中显示错误消息时,它会跳过(我认为)代码块if 语句并直接进入 foreach 循环,该循环应该仅在没有错误消息时才被激活。然后我得到这个错误:
这是 Razor 视图的代码 DetailsBySurname.cshtml:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "DetailsBySurname";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@if (ViewBag.Message != null)
{
<p class="alert-@(ViewBag.Error != null ? "danger" : "success")">@(ViewBag.Message)</p>
if (ViewBag.Error != null)
{
<ul>
@foreach (Exception e in ViewBag.Exception.ValidationExceptions)
{
<li class="alert-danger">@(e.Message)</li>
}
</ul>
}
}
<h1>Details</h1>
<div>
<h4>Employee</h4>
<hr />
@foreach (var item in Model)
{
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.FirstName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.FirstName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => item.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.LastName)
</dd>
</dl>
}
</div>
这是控制器中用于 IAction 结果的代码块 DetailsBySurname:
public async Task<IActionResult> DetailsBySurname(string lastName)
{
if (Request.Query.Count > 0)
{
try
{
ValidationException exception = new ValidationException();
lastName = !string.IsNullOrWhiteSpace(lastName) ? lastName.Trim() : null;
using (CompanyContext context = new CompanyContext())
{
if (string.IsNullOrWhiteSpace(lastName))
{
exception.ValidationExceptions.Add(new Exception("Last Name Not Provided"));
}
// Category ID fails parse.
// Common validation points (5) and (5a).
int n;
bool isNumeric = int.TryParse(lastName, out n);
if (isNumeric)
{
exception.ValidationExceptions.Add(new Exception("ID Not Valid string"));
}
else
{
// Category ID exists.
// Common validation point (7).
if (!context.Employees.Any(x => x.LastName == lastName))
{
exception.ValidationExceptions.Add(new Exception("Last Name Does Not Exist"));
}
}
if (exception.ValidationExceptions.Count > 0)
{
throw exception;
}
}
var employees = _context.Employees.Where(m => m.LastName == lastName);
ViewBag.Message = $"Successfully Found {lastName}!";
return View(employees);
}
// Catch ONLY ValidationException here.
catch (ValidationException e)
{
ViewBag.LastName = lastName;
ViewBag.Message = "There exist problem(s) with your submission, see below.";
ViewBag.Exception = e;
ViewBag.Error = true;
return View(e);
}
}
return View();
}
最后是 Index.cshtml 视图中搜索字段的代码:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
</li>
<li class="nav-item dropdown">
<form action="/Employee/Index" method="get">
<lable for="filter"> Show Laid of Staff</lable>
<input type="checkbox" id="filter" name="filter" value="laidoff" />
<input class="btn btn-outline-success my-2 my-sm-0" type="submit" value="Go!" />
</form>
</li>
</ul>
<form action="/Employee/DetailsByEmail" method="get" class="form-inline my-2 my-lg-0">
<input id="email" name="email" data-val="true" data-val-required="Email is required" class="form-control mr-sm-2" type="search" placeholder="Search by Email" aria-label="Search">
<span class="field-validation-valid" data-valmsg-for="email" data-valmsg-replace="true"></span>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
<form action="/Employee/DetailsBySurname" method="get" class="form-inline my-2 my-lg-0">
<input id="lastName" name="lastName" data-val="true" data-val-required="Last Name is required" class="form-control mr-sm-2" type="search" placeholder="Search by Last Name" aria-label="Search">
<span class="field-validation-valid" data-valmsg-for="lastName" data-valmsg-replace="true"></span>
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
我看到调试一直按预期进行,直到最后,只有当它跳转到 Razor View 时,它才会给我上面提到的这个错误。 我还创建了 Class 来处理所有验证异常,但它工作正常。我确定问题出在 Controller 和 Razor 视图之间。或者可能是其他地方的问题,我是 ASP .Net MVC 的新手,有什么建议吗?
我用不同的验证方法修复了它。 对于 DetailsBySurname 我删除了 if(ViewBag... 并添加了不同的 if(ViewData... - 语句来检查返回的结果是否为 null 然后不要 运行 foreach 循环). 要捕获错误消息,请使用另一个 if 语句 @if(!ViewData.ModelState.IsValid) ,如下所示:
@model IEnumerable<codeRed_Capstone.Models.Employee>
@{
ViewData["Title"] = "DetailsBySurname";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Details</h1>
<div>
@if (ViewData.ModelState.IsValid)
{
<h4>Employee</h4>
<hr />
@foreach (var item in Model)
{
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.FirstName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.FirstName)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(item => item.LastName)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(modelItem => item.LastName)
</dl>
}
}
</div>
<div class="form-row">
<div class="form-group col-md-2">
@if (!ViewData.ModelState.IsValid)
{
<span class="field-validation-error">@ViewData.ModelState["LastName"].Errors[0].ErrorMessage</span>
}
</div>
</div>
然后在 IAction 结果 DetailsBySurname 的控制器中,我将验证方法更改为内置验证,如下所示:
public async Task<IActionResult> DetailsBySurname(string lastName)
{
lastName = !string.IsNullOrWhiteSpace(lastName) ? lastName.Trim() : null;
if (string.IsNullOrWhiteSpace(lastName))
{
ModelState.AddModelError("LastName", "Last Name not Provided");
//exception.ValidationExceptions.Add(new Exception("Last Name Not Provided"));
}
bool exists;
if (!(exists = _context.Employees.Any(m => m.LastName == lastName)))
{
//return NotFound(new Exception("Email not found"));
ModelState.AddModelError("LastName", "Last Name not found");
}
if (!ModelState.IsValid)
{
return View();
}
else
{
var employee = _context.Employees.Where(m => m.LastName == lastName);
return View(employee);
}
}