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"> </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?
You can use the
[Bind(Prefix="Cycle")]
attribute to 'strip' the prefix so thatname="Cycle.PDFResourceLibrary"
effectively becomesname="PDFResourceLibrary"
and will bind to yourPDFResourceRequestViewModel