【问题标题】:MVC 5 - two separate models on a page, how do I attach one to a form so I can submit it?MVC 5 - 页面上有两个单独的模型,如何将一个附加到表单以便提交?
【发布时间】:2016-05-28 11:43:51
【问题描述】:

TL;DR:如何处理以非标准数据名称提交的表单数据?

统计数据:

  • MVC 5
  • ASP.NET 4.5.2

我引入了两种不同的模型:

public async Task<ActionResult> Index() {
  var prospectingId = new Guid(User.GetClaimValue("CWD-Prospect"));
  var cycleId = new Guid(User.GetClaimValue("CWD-Cycle"));
  var viewModel = new OnboardingViewModel();
  viewModel.Prospecting = await db.Prospecting.FindAsync(prospectingId);
  viewModel.Cycle = await db.Cycle.FindAsync(cycleId);
  return View(viewModel);
}

一个叫Prospecting,另一个叫Cycle。 Prospecting 工作正常,因为页面上除了一个小项目之外没有其他需要它。

Cycle 页面上有一堆单独的表单,每个表单都需要单独提交,并且只编辑 Cycle 表的一小部分。我的问题是,我不知道如何将正确的数据提交到后端。我也不完全确定如何“捕捉”这些数据。

亮点是前端显然正确地反映了数据库中的内容。例如,如果我手动将 db 字段更改为 true 值,则该复选框最终会在刷新时被选中。

我现在的形式是这样的:

@using(Html.BeginForm("UpdatePDFResourceRequest", "Onboarding", FormMethod.Post, new { enctype = "multipart/form-data" })) {
  @Html.AntiForgeryToken()
  @Html.ValidationSummary(true, "", new { @class = "text-danger" })
  <fieldset>
    @Html.LabelFor(Model => Model.Cycle.PDFResourceLibrary, htmlAttributes: new { @class = "control-label" })
    @Html.CheckBoxFor(Model => Model.Cycle.PDFResourceLibrary, new { @class = "form-control" })
    @Html.ValidationMessageFor(Model => Model.Cycle.PdfResourceLibrary, "", new { @class = "text-danger" })
    <label class="control-label">&nbsp;</label><button type="submit" value="Save" title="Save" class="btn btn-primary glyphicon glyphicon-floppy-disk"></button>
  </fieldset>
}

但是生成的 HTML 是这样的:

<input id="Cycle_PDFResourceLibrary" class="form-control" type="checkbox" value="true" name="Cycle.PDFResourceLibrary" data-val-required="'P D F Resource Library' must not be empty." data-val="true">

如您所见,name=Cycle.PDFResourceLibrary,我不知道如何在后端捕获它。

我对该特定表格的模型是:

public class PDFResourceRequestViewModel {
  [DisplayName("PDF Resource Library Request")]
  public bool PDFResourceLibrary { get; set; }
  [DisplayName("Date Requested")]
  [DataType(DataType.Date)]
  public DateTime PDFResourceLibraryDate { get; set; }
  [DisplayName("Notes")]
  public string PDFResourceLibraryNotes { get; set; }
}

(虽然不是该表的整体模型) 而处理表单提交的方法是:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> UpdatePDFResourceRequest(PDFResourceRequestViewModel model) {
  var id = new Guid(User.GetClaimValue("CWD-Cycle"));
  Cycle cycle = await db.Cycle.FindAsync(id);
  if(cycle == null) {
    return HttpNotFound();
  }
  try {
    cycle.CycleId = id;
    cycle.PDFResourceLibrary = model.PDFResourceLibrary;
    cycle.PDFResourceLibraryDate = DateTime.Now;
    cycle.PDFResourceLibraryNotes = model.PDFResourceLibraryNotes;
    db.Cycle.Add(cycle);
    await db.SaveChangesAsync();
    return RedirectToAction("Index");
  } catch { }
  return View(model);
}

现在,我知道该方法是错误的,因为我只编辑了该表中几十个值中的三个值,所以我需要使用类似 this method 的东西。问题是,表单是使用Cycle.PDFResourceLibraryname= 提交的,并且在后端没有匹配。

帮助?

【问题讨论】:

    标签: asp.net asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6


    【解决方案1】:

    您可以使用[Bind(Prefix="Cycle")] 属性“去除”前缀,以便name="Cycle.PDFResourceLibrary" 有效地变为name="PDFResourceLibrary" 并绑定到您的PDFResourceRequestViewModel

    public async Task<ActionResult> UpdatePDFResourceRequest([Bind(Prefix="Cycle")]PDFResourceRequestViewModel model)
    

    【讨论】:

    • 这正是我需要的工具。非常感谢!我现在唯一的问题是通过 ViewBag 引入了一个下拉菜单,但我似乎无法将其名称更改为 Cycle.DropDown;它纯粹显示为 DropDown,因此不会与其他表单项一起“收获”。建议?
    • 您的问题/代码中没有关于下拉菜单的内容。您可以编辑它,以便我了解您在做什么以及如何渲染该下拉列表。例如,如果您使用部分渲染它,您可以使用 AdditonalViewData 传递前缀。另一种选择是在方法中有 2 个参数,第二个是 string dropDown,以便填充所选值。跨度>
    猜你喜欢
    • 2012-11-29
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2014-07-01
    • 1970-01-01
    相关资源
    最近更新 更多