首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.Net Core Ajax表单提交,并对少数ViewModel属性进行ModelState验证

ASP.Net Core Ajax表单提交,并对少数ViewModel属性进行ModelState验证
EN

Stack Overflow用户
提问于 2016-10-17 13:40:28
回答 2查看 4.3K关注 0票数 2

问题

我有一个客户端视图模型,它包含一些必需的属性和非必需的属性。视图包含用于更新不同视图模型属性的不同部分。如果我用需要的客户端详细信息(如FirstName、LastName、道布等)更新视图的一部分,那么我可以将输入类型包装到ajax表单中,控制器将从视图模型中获取这些属性,并相应地使用ModelState.IsValid进行验证,验证就会成功。但是,如果我在同一视图上有另一节需要更新视图模型(即Notes)上的非必需属性,并将其从ajax表单post中传递出去,那么ModelState验证就会失败,因为其他必需的属性是空的,因为它们从未作为ajax表单的一部分提交。请注意,在加载客户端详细信息页之前,所需字段应该始终填充数据,因此不应该为null。

代码

ViewModel

代码语言:javascript
复制
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; }
}

视图

代码语言:javascript
复制
@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>

控制器

代码语言:javascript
复制
[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. 如何在控制器内有效地对某些字段执行ModelState验证而不重复代码?我搜索了这个问题,并注意到类似于ModelState[].Errors.Clear()这样的选项;但是由于这将是一个大视图,有许多不同的部分可供更新,所以对于我需要执行的所有小型ajax帖子,我希望避免在不同的操作方法中重复这些语句。基本上,我希望使用ModelState验证,这样我就可以将我的验证逻辑存储在ViewModel中,而不是分离和/或复制控制器中的任何验证逻辑。
  2. 我可以看到的另一个选择是在我所拥有的每个ajax表单中将所有所需的属性作为隐藏的输入类型,但这似乎是可怕的、没有必要的,而且肯定是一场噩梦。是否有更好的方法来传递ajax帖子的所有ViewModel属性,如果是这样,那么发送除了利用ajax检查之外没有其他用途的ViewModel属性是否会很昂贵呢?
  3. 我是asp.net的新手,从asp.net核心mvc开始(我非常喜欢它),并且一直通过所有的教程学习,所以问题等等。然而,我是否有可能以错误的方式来处理这个问题,如果是的话,使用asp.net核心和Microsoft.jQuery.Unobtrusive.Ajax或其他ajax工具来解决这个问题的正确方法是什么?请注意,我只发布了这个问题,因为发布的其他类似问题似乎都不涉及在视图上共享ViewModel属性,而只是提交了一些属性,但利用了开箱即用的验证。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-19 08:10:20

虽然我无法得到建议的方法来按照建议行事,但我确实使用了关于将视图模型分离出来以用于呈现和提交的建议。我想我被微软ASP.NET核心网站上的电影教程引入了歧途,它在细节和编辑页面上都使用了相同的电影模型。

为了进一步解决我的问题,我已经为细节页面采用了一个大的视图模型,我将对需要更新的页面的各个部分使用view组件。这允许我为每个View组件提供一个单独的视图模型,我的控制器post操作可以只接受与相应的View组件相关的视图模型,这样它只能执行必要的ModelState验证。

来自一个jQuery ajax帖子的服务器端验证导致了关于将ModelState错误返回给客户端以供显示的下一个问题,但是我提交了一个新的问题.

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

票数 1
EN

Stack Overflow用户

发布于 2016-10-17 14:54:03

为所有调用(通过使用隐藏字段)发送所有的东西并不昂贵,但它很麻烦,不是一个直接的解决方案。

MVC中的视图模型不必是呈现页面和提交表单的同一个类。在您的示例中,您可以定义一个视图模型,用于如下所示的呈现:

代码语言:javascript
复制
public class ClientDetailViewModel {
    public ClientBasicViewModel Basics {get;set;}
    public ClientNotesViewModel Notes {get;set;}
}

然后将字段(姓名、性别等)放在两个新的类中。使用两个单独的控制器方法来处理表单提交。跟踪FirstName如何发送和接收:

  • 在呈现时,您将使用Model.Basics.FirstName来显示现有值。
  • 对于表单中的字段名,将其设置为input name="FirstName"...
  • 当向后提交表单时,控制器方法接受ClientBasicViewModel类型的参数。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40087998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档