MVC 5 - two separate models on a page, how do I at

2019-03-07 06:02发布

TL;DR: How do I handle form data that is being submitted with nonstandard names for the data?

The stats:

  • MVC 5
  • ASP.NET 4.5.2

I am bringing in two different models:

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);
}

One called Prospecting, the other called Cycle. The Prospecting one is working just fine, as nothing else on the page needs it except one small item.

The Cycle has a mess of separate forms on the page, each needing to be separately submittable, and editing just one small part of the Cycle table. My problem is, I don't know how to submit the correct data to the backend. I am also not entirely sure how to "catch" that data.

The bright spot is that apparently the front end is properly reflective of what is in the db. As in, if I manually change the db field to a true value, the checkbox ends up being selected on refresh.

My current form is such:

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

But the resulting HTML is such:

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

As you can see, the name= is Cycle.PDFResourceLibrary and I don't know how to catch this on the backend.

My model for that specific form is:

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

(not the overall model for that table, though) And the method used to handle the form submission is:

[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);
}

Now, I know that the method is wrong, for one I am editing just three values out of dozens in that table, so I need to be using something like this method. Problem is, the form is getting submitted with the name= of Cycle.PDFResourceLibrary and it is not being matched up on the back end.

Help?

1条回答
beautiful°
2楼-- · 2019-03-07 06:44

You can use the [Bind(Prefix="Cycle")] attribute to 'strip' the prefix so that name="Cycle.PDFResourceLibrary" effectively becomes name="PDFResourceLibrary" and will bind to your PDFResourceRequestViewModel

public async Task<ActionResult> UpdatePDFResourceRequest([Bind(Prefix="Cycle")]PDFResourceRequestViewModel model)
查看更多
登录 后发表回答