【问题标题】:Model binding showing errors with adequate data being provided模型绑定显示错误并提供足够的数据
【发布时间】:2012-04-24 16:28:30
【问题描述】:

我遇到了一个正在验证的字段,该字段看似未通过验证,但没有完成要求。我会尽量包含所有信息,所以对于这么长的问题帖子深表歉意!

已创建的 ViewModel 是一个 DTO 对象,其中包含足够的信息来操作用户输入的任何数据。由于项目数量未知,我的视图模型比理想模型稍微复杂...

public class UpdateViewModel
{
    public UpdateViewModel()
    {
        WorkingPeriods = new List<WorkingPeriod>();
        LeavePeriods = new List<LeavePeriod>();
    }

    public Guid UserID { get; set; }
    public DateTime From { get; set; }
    public DateTime Until { get; set; }
    public DateTime Selected { get; set; }

    public IEnumerable<WorkingPeriod> WorkingPeriods { get; set; }
    public IEnumerable<LeavePeriod> LeavePeriods { get; set; }

    public class WorkingPeriod
    {
        public int ID { get; set; }
        public DateTime Date { get; set; }
        public TimeSpan? StartTime { get; set; }
        public TimeSpan? EndTime { get; set; }
    }

    public class LeavePeriod
    {
        public int ID { get; set; }
        public DateTime Date { get; set; }
        public int LeaveTypeID { get; set; }
        public Guid? Reference { get; set; }
        public string Period { get; set; }
        public TimeSpan? UserDefinedPeriod { get; set; }
    }
}

我的观点是,借助几个静态助手的助手,可以生成代表信息存在的 HTML。输出 HTML 类似于:

<li class="editorRow">
    <input type="hidden" name="LeavePeriods.index" autocomplete="off" value="8a5522c6-57fe-40a2-95bc-b9792fbe04d3" />
    <input id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__ID" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].ID" type="hidden" value="4" />
    <input id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__Date" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].Date" type="hidden" value="23/04/2012 00:00:00" />
    <select class="leaveTypeDropdown" id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__LeaveTypeID" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].LeaveTypeID">
        <option value="">- please select -</option>
        <option selected="selected" value="2">Annual Leave</option>
        <option value="34">Public Holiday</option>
        <option value="1">Sickness</option>
    </select>
    <div class="leavePeriodRadio">
    <input checked="checked" id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__ALL" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].Period" type="radio" value="ALL" /><label for="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__ALL">Full Day</label>
        <input id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__AM" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].Period" type="radio" value="AM" /> <label for="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__AM">AM</label>
        <input id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__PM" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].Period" type="radio" value="PM" /> <label for="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__PM">PM</label>
        <input class="other-user-period" id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__Other" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].Period" type="radio" value="Other" /> <label for="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__Other">Other</label>
        <span class="user-defined" style="display:none">
            Duration: <input class="timepicker" id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__UserDefinedPeriod" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].UserDefinedPeriod" type="text" value="" />
        </span>
    </div>
</li>

当用户使用 Ajax(通过 Ajax.BeginForm 构造设置)提交表单时出现此问题(涉及 MVC3 和 JQuery)。

@using (Ajax.BeginForm("Index", "Timesheet", new AjaxOptions()
    {
        HttpMethod = "POST",
        LoadingElementId = "loading",
        UpdateTargetId = "contentPane",
        OnComplete = "SaveCompleted",
    }))
  • 如果用户省略了该字段(他们完全有权这样做),他们会收到消息:The UserDefinedPeriod field is required.
  • 或者,如果他们输入有效的 TimeSpan 值(例如“12:00”),他们会得到:The value '12:00' is not valid for UserDefinedPeriod.
  • 如果他们输入了无效的字符串(例如“Boris”),则该值会被清除,并且会显示上面的必填字段消息,就好像他们没有输入任何内容一样。 (假设:我相信该值已被清除,因为“Boris”不能存储在 TimeSpan? 中,因此不能传输回视图)

使用断点并检查各种事物的值,我得出以下结论:

  • 该值存在于 Request.Form 中,并且可以与与其分组的其他值一起看到。
  • 该值存在于模型中,可以通过使用 VS 中的断点检查它来查看。
  • ModelState.IsValid 正在返回false,因为 Model.LeavePeriods.UserDefinedPeriod 有 1 个错误,与最终显示给用户的错误相同。

作为参考,控制器是:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class TimesheetController : Controller
{
    [HttpPost]
    public ActionResult Index(UpdateViewModel updates, User currentUser)
    {
        if (!ModelState.IsValid)
        {
           // error with model, so lets deal with it and return View();
        }
        // continue with parsing and saving.
    }
}

这个问题最让我困惑的是,我有其他以类似方式构建的盒子,不会导致任何问题 - 例如 WorkingPeriod 可枚举中的 TimeSpan?s。关于我可以在哪里查看可能是什么问题,我已经没有想法了。我尝试将 ViewModel 的预期值从 TimeSpan? 更改为正常的 string,没有明显差异(即使错误消息相同)。

我猜这个问题要么超出了我在下面详述的范围(不过,控制器和模型相对来说比较普通,所以我不知道还能去哪里看),或者我还有其他问题不了解模型绑定(关于模型绑定,我已经有很多不明白的地方了!)。

【问题讨论】:

    标签: asp.net-mvc-3 data-annotations model-binding


    【解决方案1】:

    我已经设法解决了这个问题,但我不太确定为什么我已经修复了,修复了它。

    基本上,在 UpdateViewModel 中,我将“UserDefinedPeriod”更改为“OtherPeriod”。

    public class LeavePeriod
    {
        public int ID { get; set; }
        public DateTime Date { get; set; }
        public int LeaveTypeID { get; set; }
        public Guid? Reference { get; set; }
        public string Period { get; set; }
        public TimeSpan? OtherPeriod { get; set; }
    }
    

    然后显然更改了我代码中其他地方的所有代码引用,包括视图:

    <span class="user-defined" style="display:none">
        Duration: <input class="timepicker" id="LeavePeriods_8a5522c6-57fe-40a2-95bc-b9792fbe04d3__OtherPeriod" name="LeavePeriods[8a5522c6-57fe-40a2-95bc-b9792fbe04d3].OtherPeriod" type="text" value="" />
    </span>
    

    这似乎解决了这个问题。我不确定改变工作的具体原因是什么 - 所以我对任何可能导致它的原因持开放态度。但是,此调整对我来说是解决方案,并且可能对将来遇到此问题的其他人有用。

    【讨论】:

      猜你喜欢
      • 2021-12-11
      • 1970-01-01
      • 2020-06-18
      • 1970-01-01
      • 2018-10-21
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多