Razor Pages - 由于多个对象共享参数,模型验证失败

Hel*_*123 5 c# asp.net-core-mvc asp.net-core razor-pages

我遇到了一个我似乎无法解决的问题。我正在使用 Razor Pages 并且有两个可以绑定的对象。

[BindProperty]
public MeetingMinuteInputDto MeetingToCreate { get; set; }

[BindProperty]
public MeetingMinuteUpdateDto MeetingToUpdate { get; set; }
Run Code Online (Sandbox Code Playgroud)

以上两个是单独的 dto,用于在我的数据库中创建/更新基本实体。我有两个单独的 dto,因为我只允许更新特定项目(以防止过度发布)。这两个类有NameDateReminder。该MeetingMinuteUpdateDto只允许Date被改变。

名称属性是必需的,不能为空。我在同一个页面/控制器中拥有两个对象的原因是因为我使用模态来创建/更新,我宁愿不创建多个页面来创建/编辑对象。

我有两种用户可以填写的表单 - 一种用于编辑,一种用于创建。每个都将值绑定到一个特定的对象(即创建表单将其发布的表单值绑定到MeetingMinuteInputDto)。

<div class="form-group">
    <div class="col-md-10">
          <label asp-for="MeetingToCreate.Name" class="control-label"></label>
          <input asp-for="MeetingToCreate.Name" class="form-control" />
          <span asp-validation-for="MeetingToCreate.Name" class="text-danger"></span>
      </div>
</div>
Run Code Online (Sandbox Code Playgroud)

以上是我用于创建新会议的表单示例。我检查了一下,当提交表单时,只有MeetingMinuteInputDto值被绑定。另一个对象 ( MeetingMinuteUpdateDto) 的所有属性都为空值。

但是当我检查模型状态时,MVC 会在“Name”属性上抛出一个错误,指出它为空。我查看了模型状态的结果,有一个名为“Name”的键,它与任何未通过验证的对象无关。

如果我MeetingMinuteUpdateDto从页面中删除另一个对象(即我删除)并进行模型绑定,则一切正常。如何防止模型验证尝试验证与当前操作无关的对象?我希望 Create 操作仅验证创建对象,反之亦然。

我尝试这样做,TryValidateModel(MeetingToCreate)但这也为模型验证提供了错误。

在此处输入图片说明

注意:我不能只是将对象属性放在外面,因为我还有其他页面需要这样做,其中更新/创建对象有 10 多个共享/不共享的属性。


更新- 我可以从模型状态字典中手动删除验证错误。但我真的不喜欢这种方法,因为我不想遍历所有不正确键的属性并删除它们。


更新 2:以下是有关何时发生此问题的更多详细信息:

public class MeetingMinuteInputDto: MeetingMinuteManipulationDto
    {
        public string AdditionalInfo { get; set; }
    }

public class MeetingMinuteUpdateDto : MeetingMinuteManipulationDto
    {
    }

public class MeetingMinuteManipulationDto
    {
        [Required]
        public string Name { get; set; }
        public IFormFile FileToUpload { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

在我的 Razor 页面中,我拥有这两个带有 bind 属性的属性:

public class MeetingMinutesModel : PageModel
    {
        [BindProperty]
        public MeetingMinuteInputDto MeetingToCreate { get; set; }

        [BindProperty]
        public MeetingMinuteUpdateDto MeetingToUpdate { get; set; } 
        //...stuff
}
Run Code Online (Sandbox Code Playgroud)

我在创建/编辑页面上的表单如下所示:

<form asp-page="/MeetingMinute/MeetingMinutes" asp-page-handler="CreateMeeting">
    <div class="form-group">
        <div class="col-md-10">
              <label asp-for="MeetingToCreate.Name" class="control-label"></label>
              <input asp-for="MeetingToCreate.Name" class="form-control" />
              <span asp-validation-for="MeetingToCreate.Name" class="text-danger"></span>
          </div>
    </div>
    //other inputs and label for rest of the properties
   <button type="submit" class="btn btn-danger">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

表单的输入设置为专门绑定到MeetingToCreate属性。当我提交表单时,表单值被正确绑定。但与此同时,我收到了该MeetingToUpdate属性的ModelState 错误(因为它与 共享某些字段MeetingToCreate)。

我假设在 Razor 页面中,模型状态验证正在验证MeetingMinutesModel而不是单个MeetingToCreate/MeetingToUpdate属性。在 MVC 中,我认为这可能会有所不同,因为操作需要具有参数,而不是剃刀页面中页面模型上的开放式属性。

小智 5

我正在做类似的事情。在搜索任何解决方案时,我找到了您的问题,但没有找到我分享的解决方案。

我实现了多个 BindProperty 和多个 OnPost Actions,我找到的解决方案是使用 [Bind] 属性在 Asp.Net MVC 中执行一些操作。

就你而言,确实如此。

public class MeetingMinutesModel : PageModel
{
    //[BindProperty] remove it
    public MeetingMinuteInputDto MeetingToCreate { get; set; }

    //[BindProperty] remove it
    public MeetingMinuteUpdateDto MeetingToUpdate { get; set; }
    //...stuff
}

public IActionResult OnPost([Bind("Name, FileToUpload, AdditionalInfo")] MeetingMinuteInputDto MeetingToCreate)
{
    //Do somthing
}
Run Code Online (Sandbox Code Playgroud)


Xue*_*hen 1

在 Razor 页面中,页面中的 @model 是PageModel,类的“Name”MeetingMinuteManipulationDto属性是Required,因此模型状态验证会验证 PageModel 中的所有属性。如果您坚持最初的想法,您可以尝试使用ViewComponent在同一个剃刀视图中实现创建/编辑对象。