【问题标题】:Post view model instance back to several action methods将视图模型实例发布回几个操作方法
【发布时间】:2015-04-24 18:10:55
【问题描述】:

我有一个ViewModel,它有 8 个属性,其中 6 个是复杂类型。我必须将它们显示在 3 组中,最后将所有数据保存到数据库中。现在,我为此创建了两个方法,第一个将用HttpGet 装饰,第二个用HttpPost 装饰。我已经在一个.cshtml 中创建了所有这三个组。第一次,只有第一组可见。在点击 NEXT 按钮后,我将在 Javascript/Jquery的帮助下使第二组可见,而第一组将不可见>。然后第三组将可见。并且在最后一部分中必须出现提交按钮。单击此按钮后,我会将整个模型发布回操作方法。但是,在这种情况下,我有两个问题:

  • 我必须通过客户端验证仅验证可见字段
  • 如果客户端验证以某种方式通过而服务器端没有通过,那么我必须找到并显示未验证的部分。

所以,为了解决这些问题,我决定两个创建四个动作方法,它们会将视图模型发布回另一个。 为了清楚起见,我想这样展示:

  1. 创建视图模型[HttpGet]
  2. 转到第二部分[HttpPost]
  3. 转到第三部分[HttpPost]
  4. 保存到数据库[HttpPost]

1 会将我的 viewmodel 实例返回到 2,然后 2 会将其发布到 3,然后 3 会将其发布到 4。

这是好方法吗?如果没有,你会推荐我什么?

【问题讨论】:

  • 有趣的问题,但因为您似乎有一个可行的解决方案,我想知道它是否更适合 CodeReview SE?
  • 这可能会有所帮助c-sharpcorner.com/UploadFile/4b0136/… 我会推荐向导方法
  • @xDaevax 这是关于 CR 的题外话,没有要审查的工作实现,必须在问题中发布。
  • @Hosch250 确实如此。我假设作者可以提供这些细节。尽管我认为在此处包含该详细信息对于 this 站点来说是题外话。
  • @xDaevax "How should I do x" with a working implementation 对于 SO 来说不是题外话。此外,问题可以在多个站点上成为主题。使用代码,这将非常适合 CR,但这并不意味着它会使其脱离 SO。

标签: c# asp.net-mvc asp.net-mvc-4 razor


【解决方案1】:

您当前的方法意味着多次发布/重定向和某种形式的临时存储库或模仿视图状态的东西。更好的方法是在一个表单中完成所有操作,并使用 Validator.element(element) 验证每个部分中的各个控件

在下一步按钮.click() 事件中

  1. 选择关联<section> 中的所有控件 - 例如var controls = $(this).closest('section').find('input, textarea, select');
  2. $.each 循环中,调用$('form').validate().element($(this));
  3. 使用$(this).valid(); 测试该部分中的控件是否有效
  4. 如果一切都有效,隐藏当前部分并显示下一个

最后一部分包括执行正常提交的“保存”按钮

查看

<section>
    <h2>Section 1</h2>
    @Html.LabelFor(m => m.SomeProperty)
    @Html.TextBoxFor(m => m.SomeProperty)
    @Html.ValidationMessageFor(m => m.SomeProperty)
    ....
    <div class="error"></div>
    <button type="button" class="next">Next</button>
</section>
<section>
    <h2>Section 2</h2>
    // Your inputs and validation
    <div class="error"></div>
    <button type="button" class="next">Next</button>
<section>
<section>
    <h2>Section 3</h2>
    // Your inputs and validation
    <div class="error"></div>
    <button type="submit" class="next">Submit</button> // submit button for last section
</section>

css(隐藏除第一部分以外的所有部分)

section:not(:first-of-type) {
    display:none;
}

脚本

$('button').click(function () {
  var container = $(this).closest('section');
  var isValid = true;     
  $.each(container.find('input'), function () { // include select, textarea as required
    $('form').validate().element($(this));
    if (!$(this).valid()) {
      isValid = false;
      return false;
    }
  });
  if (isValid) {
    container.next('.section').show().find('input').first().focus();
    container.hide();
  } else {
    container.find('.error').text('please complete');
  }
});

这将解决所有客户端验证,而无需多次发布/重定向。至于在由于模型仍然无效而不得不返回视图的罕见情况下会发生什么(将生成错误消息但可能在隐藏部分中,因此最初不可见)

  1. 只需让用户再次单步执行“向导”(可能会造成混淆) 如果在第一部分中看不到错误)
  2. 使用 jquery 查找生成的错误,例如 $('span.field-validation-error) 并取消隐藏关联 父部分

【讨论】:

  • 感谢您的回答。其实我已经想过这个,并且已经创造了这个的90%。但后来我认为可能有更好的选择更适合 Asp.Net MVC。但是,好像没有。再次感谢。
【解决方案2】:

在我看来,您正在尝试制作一个巫师。使用相同的视图模型但只显示该页面所需的字段(将其他字段放入隐藏字段以保存数据),将您的页面分成部分会更容易。然后,您可以让 AJAX 回调您的控制器以呈现下一页/上一页,这将防止屏幕闪烁,使其看起来像页面没有更改。

【讨论】:

  • FWIW,我建议不要使用隐藏字段。 1:这是额外的开销/有效负载,2:可以修改它们。授予验证应该处理后者,但无需继续移交。
  • @PatrickHofman:我仍然相信只发送相关信息并保留隐藏项目(最大)用于实体的 PK 和“人工验证”值等内容。
  • 确实如此。您也可以将其保存在数据库中。那将是我的首选位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 2019-05-20
  • 2016-09-08
  • 1970-01-01
相关资源
最近更新 更多