gpt4 book ai didi

c# - ASP.Net Core MVC - 在几个 ViewModel 属性上使用 ModelState 验证的 Ajax 表单提交

转载 作者:太空宇宙 更新时间:2023-11-03 12:38:16 25 4
gpt4 key购买 nike

问题

我有一个具有一些必需属性和非必需属性的客户端 View 模型。该 View 包含用于更新不同 View 模型属性的不同部分。如果我使用所需的客户端详细信息(如名字、姓氏、DOB 等)更新 View 的一部分,那么我可以将输入类型包装到 ajax 表单中, Controller 将从 View 模型中获取这些属性并使用 ModelState 进行相应验证.IsValid 和验证将成功。但是,如果我在同一 View 上有另一个部分需要更新 viewmodel 上的非必需属性(即 Notes)并从 ajax 表单发布传递它,则 ModelState 验证失败,因为其他必需属性为 null,因为它们从未提交过作为 ajax 表单的一部分。请注意,必填字段应始终在加载客户详细信息页面之前填充数据,因此绝不能为空。

代码

View 模型

public class ClientDetailViewModel
{

public int ID { get; set; }

[Required]
[StringLength(50, MinimumLength = 2)]
public string FirstName { get; set; }

[Required]
[StringLength(50, MinimumLength = 2)]
public string LastName { get; set; }

[Required]
[Display(Name = "Date of Birth")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }

[Required]
public string Gender { get; set; }

public string Notes { get; set; }
}

查看

@model MSIC.Models.ClientViewModels.ClientDetailViewModel
@inject MSIC.Services.Custom.IGenderService GenderService;

<!-- tab-pane for updating core client details -->
<div class="tab-pane active" id="tab_1">
<form asp-controller="Client" asp-action="Edit" class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input asp-for="FirstName" class="form-control" />
<span asp-validation-for="FirstName" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="LastName" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="DOB" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input asp-for="DOB" class="form-control" />
<span asp-validation-for="DOB" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="Gender" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<select asp-for="Gender" asp-items="@(new SelectList(GenderService.GetAll(),"Code","Name"))" class="form-control">
</select>
<span asp-validation-for="Gender" class="text-danger" />
</div>
</div>
</form>
</div>

<!-- different section for updating client notes -->
<div id="divNotes" class="center-block">@Model.Notes</div>
<a href="#" class="btn btn-danger btn-block" data-toggle="modal" data-target="#notesModal" role="button"><b>Edit Notes</b></a>
<form asp-controller="Client" asp-action="EditNotes" class="form-horizontal" data-ajax="true" data-ajax-method="POST" data-ajax-update="#divNotes" data-ajax-mode="replace" data-ajax-success="CloseModal('#notesModal')" data-ajax-failure="AjaxOnFailure(xhr, status, error)">
<div class="modal fade" id="notesModal" tabindex="-1" role="dialog" aria-labelledby="notesModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="notesModalLabel">edit Reason</h4>
</div>
<div class="modal-body">
<input type="hidden" asp-for="ID" />
<div class="form-group">
<div class="col-sm-10">
<textarea asp-for="Notes" class="form-control" autofocus></textarea>
<span asp-validation-for="Notes" class="text-danger" />
</div>
</div>
</div>
<div class="modal-footer">
<div class="text-danger pull-left">
<i id="modalErrorIcon" class=""></i>
<span id="modalErrorText"></span>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</form>

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult EditNotes(ClientDetailViewModel model)
{
//validation fails because required fields in model are null since they were not submitted with this ajax form
if (ModelState.IsValid)
{
//update database with client notes and return notes to screen
return Content(model.Notes);
}

return Content("i haven't coded this yet");
}

问题

  1. 如何在不重复代码的情况下以高效的方式仅对某些字段在 Controller 内执行 ModelState 验证?我搜索了这个问题并知道像 ModelState[].Errors.Clear(); 这样的选项但由于这将是一个大 View ,有许多不同的部分可供更新,我想避免在不同的 Action 方法中为我需要执行的所有小 ajax 帖子重复这些语句。基本上我想使用 ModelState 验证,这样我就可以将我的验证逻辑存储在 ViewModel 中,而不是在 Controller 中分离和/或复制任何验证逻辑。

  2. 我可以看到的另一个选项是将所有必需的属性作为隐藏输入类型包含在我拥有的每个 ajax 表单中,但这似乎非常不必要,而且肯定是维护起来的噩梦。有没有更好的方法来传递 ajax 帖子的所有 ViewModel 属性?如果是这样,发送除了利用 ModelState.IsValid 检查之外未使用的 ViewModel 属性会很昂贵吗?

  3. 我是 asp.net 的新手,已经开始使用 asp.net core mvc(我很喜欢它),并且一直在通过所有教程、SO 问题等进行学习。但是有没有可能我正在以错误的方式处理这个问题,如果是的话,使用 asp.net core 和 Microsoft.jQuery.Unobtrusive.Ajax 或其他一些 ajax 工具解决这个问题的正确方法是什么?请注意,我只发布了这个问题,因为发布的其他类似问题似乎都没有涉及在 View 上共享 ViewModel 属性,而是只提交了一些属性,但利用了开箱即用的验证。

提前致谢。

最佳答案

虽然我无法获得推荐的方法来按照建议的方式行事,但我确实使用了关于分离 View 模型以进行渲染和提交的建议。我想我被 Microsoft ASP.NET Core 网站上的电影教程误导了,该网站对详细信息页面和编辑页面使用相同的电影模型。

为了解决我以后的问题,我为详细信息页面采用了一个大 View 模型,我将对需要更新的页面的各个部分使用 View 组件。这允许我为每个 View 组件创建一个单独的 View 模型,并且我的 Controller 后操作可以只接受与相应 View 组件相关的 View 模型,因此它可以只执行必要的 ModelState 验证。

这个来自 jQuery ajax 帖子的服务器端验证让我想到了下一个关于将 ModelState 错误返回给客户端进行显示的问题,但我已经为此提交了一个新问题......

Returning BadRequest in ASP.Net Core MVC to Microsoft jQuery Unobtrusive Ajax post has ModelState undefined

关于c# - ASP.Net Core MVC - 在几个 ViewModel 属性上使用 ModelState 验证的 Ajax 表单提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40087998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com