剃刀页面-模型验证由于多个对象共享参数而失败

时间:2019-01-07 03:56:22

标签: c# asp.net-core asp.net-core-mvc razor-pages

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

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

[BindProperty]
public MeetingMinuteUpdateDto MeetingToUpdate { get; set; }

以上两个是单独的dto,用于在数据库中创建/更新基本实体。我有两个单独的dto,因为我只允许特定的项目进行更新(以防止发布过多)。这两个类都有一个NameDateReminderMeetingMinuteUpdateDto仅允许更改Date

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

我有两种用户可以填写的表格-一种用于编辑,一种用于创建。每个人都将值绑定到特定对象(即创建表单会将其发布的表单值绑定到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>

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

但是当我检查模型状态时,MVC会在“名称”属性上引发错误,指出它为null。我查看了模型状态的结果,有一个名为“名称”的键,该键不与任何未通过验证的对象绑定。

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

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

enter image description here

注意:我不能将对象属性放到外面,因为我需要在其他页面上执行此操作,其中更新/创建对象具有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; }
    }

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

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

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

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

<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>

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

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

2 个答案:

答案 0 :(得分:1)

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

我实现了多个BindProperty和多个Actions OnPost, 我发现的解决方案是使用[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
}

答案 1 :(得分:0)

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