提问人:s15199d 提问时间:7/27/2023 最后编辑:Qing Guos15199d 更新时间:7/31/2023 访问量:89
不显眼的 Ajax 与不显眼的验证
Unobtrusive Ajax w/ Unobtrusive Validation
问:
我有一个带有单个文本框的表单。绑定到该文本框的字段是必需的。
当我发布该文本框为空的表单时,我得到了预期的结果。但是,表单仍然会触发 .ModelState.IsValid = False
data-ajax-success
相关 .cshtml
<form method="post" asp-page-handler="ProductAliasCreate" data-ajax="true" data-ajax-method="post" data-ajax-success="refreshPartial('GetAliases', 'product-aliases-container')" data-ajax-failure="handleError">
相关 .cshtml.cs
public async Task<IActionResult> OnPostProductAliasCreateAsync()
{
if (!ModelState.IsValid || _context.ProductAliases == null || ProductAlias == null)
{
return Page();
}
_context.ProductAliases.Add(ProductAlias);
await _context.SaveChangesAsync();
return Page();
}
它首先击中了那张支票。return Page();
Isvalid
如何防止 data-ajax-success
回调在 ModelState.IsValid = false
时触发?
注意:我之前有过回调,结果相同......所以我把它移到认为这将是这个问题的解决方案。refreshPartial
data-ajax-complete
data-ajax-success
答:
Return Page() 总是在你的 senaro 中返回带有 200 个雕像代码的响应,如果你想在 modelstate 无效时触发,你应该返回带有 400 个雕像代码的响应data-ajax-success
一个最小的例子,希望能有所帮助:
页面模型:
public class MyEntityModel : PageModel
{
[BindProperty(SupportsGet =true)]
public MyEntity? MyEntity { get; set; }
public void OnGet()
{
}
public async Task<IActionResult> OnPostProductAliasCreateAsync()
{
if (!ModelState.IsValid )
{
return BadRequest();
}
return new OkObjectResult("");
}
}
页:
@page
@model MyEntityModel
@{
}
<form method="post" asp-page-handler="ProductAliasCreate" data-ajax="true" data-ajax-method="post" data-ajax-success="success()" data-ajax-failure="fail()">
Id:
<input asp-for="MyEntity.Id" />
Name:
<input asp-for="MyEntity.Name" />
<input type="submit" />
</form>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-ajax-unobtrusive/jquery.unobtrusive-ajax.js"></script>
<script>
function success() {
console.log("success")
}
function fail(){
console.log("fail")
}
</script>
结果:
根据您的评论进行更新:
如果您已通过客户端验证(在我的情况下,null 检查)并在服务器上出现模型状态错误(例如,重复的名称)
如果要显示错误,则必须由于ajax调用而自己刷新页面
我的解决方案:
创建筛选器:
public class MyPageFilter : IPageFilter
{
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
}
public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
{
}
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
{
if (context.ModelState.ErrorCount != 0)
{
context.HttpContext.Response.StatusCode = 400;
}
}
}
页面模型:
[TypeFilter(typeof(MyPageFilter))]
public class EntityModel : PageModel
{
private readonly MyRazorPageApp.Areas.Identity.Data.MyRazorPageAppContext _context;
private readonly ICompositeViewEngine _viewEngine;
public EntityModel(MyRazorPageApp.Areas.Identity.Data.MyRazorPageAppContext context, ICompositeViewEngine viewEngine)
{
_context = context;
_viewEngine = viewEngine;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public MyEntity MyEntity { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
ModelState.AddModelError("MyEntity.Name", "Not Valid");
if (!ModelState.IsValid || _context.MyEntity == null || MyEntity == null)
{
return Page();
}
return RedirectToPage("./Index");
}
}
页:
@page
@model MyRazorPageApp.Pages.EntityModel
@{
}
<h1>Enyity</h1>
<h4>MyEntity</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post" data-ajax="true" data-ajax-method="post" data-ajax-success="success" data-ajax-failure="fail">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="MyEntity.Name" class="control-label"></label>
<input asp-for="MyEntity.Name" class="form-control" />
<span asp-validation-for="MyEntity.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyEntity.Prop" class="control-label"></label>
<input asp-for="MyEntity.Prop" class="form-control" />
<span asp-validation-for="MyEntity.Prop" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
<div id="mydiv"></div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-ajax-unobtrusive/jquery.unobtrusive-ajax.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
function success() {
console.log("success")
}
fail=function (response) {
console.log("fail")
var newDoc = document.open("text/html", "replace");
newDoc.write(response.responseText);
newDoc.close();
}
</script>
评论
data-ajax-success
<span asp-validation-for="ProductAlias.ProductAliasName" class="text-danger"></span>
我希望视图保持在原地,并且不显眼的验证 显示
<span asp-validation-for="ProductAlias.ProductAliasName" class="text-danger"></span>
在表单有效之前,客户端验证会阻止提交。“提交”按钮运行 JavaScript,用于提交表单或显示错误消息。
您可以添加以下代码:
<p>
ProductAlias.ProductAliasName:
<input asp-for="ProductAlias.ProductAliasName" data-val-required="This is required." data-val= "true"/>
@*<span asp-validation-for="ProductAlias.ProductAliasName" class="text-danger"></span>*@
<span data-valmsg-for="ProductAlias.ProductAliasName"
data-valmsg-replace="true"
style="margin-left: 75px; color: red;" />
</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.12/jquery.validate.unobtrusive.js"></script>
您可以阅读客户端验证以了解更多信息。
评论
return PartialView("_Errorview");
<span asp-validation-for="ProductAlias.ProductAliasName" class="text-danger"></span>