Submitting Form in MVC 4 model is null in controller post method
You are doing a foreach on the views, so the input elements should have the values posted somewhere like to this :
name="BillingCodes[0].EnterTimeHours"
, name="BillingCodes[0].EnterTimeMinutes"
you can inspect in the network tab the request on Chrome Developer Tools (CTRL+SHIFT+C)
or just viewing the source. If this is the case, you are submitting multiple BillingCodeObj objects. You must have a controller that receive that.
Take a look at the source code as this can greatly help you understand what's going on behind the scenes.
Try this on your controller:
[HttpPost]
public void SubmitTimesheet(IEnumerable<BillingCodeObj> billingCodes){
}
You can also (for debugging purposes) do
public void SubmitTimesheet(FormCollection form){}
and inspect the form how is populated on debug.
after comments and more code provided change your view to :
@using (Html.BeginForm("SubmitTimesheet", "Timesheet", FormMethod.Post))
{
@Html.EditorFor(m=>m.BillingCodes)
}
create a new cshtml in EditorTemplates/BillingCodeObj.cshtml :
@model BillingCodeObj
<div class="button-padding">
<a class="btn btn-large btn-danger btn-block billCodeBtn">
<div class="btnText">@Model.Name</div>
<div class="btnTime">@Model.TotalHours</div>
<i class="icon-chevron-down billCodeIconUp billCodeIcon"></i>
<i class="hidden icon-chevron-up billCodeIconDown billCodeIcon"></i>
</a>
<div class="content" >
<div class="row timeEntry">
<p></p>
<div class="col-12 col-lg-2">
Enter Time:
<div class="row">
<div class="col-12">
@Html.DropDownListFor(model => model.EnterTimeHours, new SelectList(new[] {
new { Value = "0", Text = "0" },
new { Value = "1", Text = "1" },
new { Value = "2", Text = "2" },
new { Value = "3", Text = "3" },
new { Value = "4", Text = "4" },
new { Value = "5", Text = "5" },
new { Value = "6", Text = "6" },
new { Value = "7", Text = "7" },
new { Value = "8", Text = "8" },
new { Value = "9", Text = "9" },
new { Value = "10", Text = "10" },
new { Value = "11", Text = "11" },
new { Value = "12", Text = "12" },
}, "Value", "Text")) <b>:</b>
@Html.DropDownListFor(model => model.EnterTimeMinutes, new SelectList(new[] {
new { Value = "0", Text = "00" },
new { Value = "15", Text = "15" },
new { Value = "30", Text = "30" },
new { Value = "45", Text = "45" },
}, "Value", "Text"))
</div>
</div>
</div>
<div class="col-lg-2"></div>
<div class="col-lg-1"></div>
<div class="control-group col-12 col-lg-2">
<label class="checkbox">
Billable @Html.CheckBoxFor(model => model.Billable)
</label>
</div>
<div class="col-12 col-lg-2">
Enter Memo:
<div class="row">
<div class="col-12">
@Html.TextAreaFor(model => model.Comment)
</div>
</div>
Brandon Knight
Updated on August 01, 2022Comments
-
Brandon Knight almost 2 years
So my problem right now is that I cant get my model into my controller when I submit this following form. I am trying to have the items from the BillingCodes (which is a list of BillingCodeObjects) loop through and display. I have removed some code from these that isn't really relevant to the situation to make it shorter and easier to read.
Here is the code for my view...
@using (Html.BeginForm("SubmitTimesheet", "Timesheet", FormMethod.Post)) { foreach (var item in Model.BillingCodes) { <div class="button-padding"> <a class="btn btn-large btn-danger btn-block billCodeBtn"> <div class="btnText">@item.Name</div> <div class="btnTime">@item.TotalHours</div> <i class="icon-chevron-down billCodeIconUp billCodeIcon"></i> <i class="hidden icon-chevron-up billCodeIconDown billCodeIcon"></i> </a> <div class="content" > <div class="row timeEntry"> <p></p> <div class="col-12 col-lg-2"> Enter Time: <div class="row"> <div class="col-12"> @Html.DropDownListFor(model => item.EnterTimeHours, new SelectList(new[] { new { Value = "0", Text = "0" }, new { Value = "1", Text = "1" }, new { Value = "2", Text = "2" }, new { Value = "3", Text = "3" }, new { Value = "4", Text = "4" }, new { Value = "5", Text = "5" }, new { Value = "6", Text = "6" }, new { Value = "7", Text = "7" }, new { Value = "8", Text = "8" }, new { Value = "9", Text = "9" }, new { Value = "10", Text = "10" }, new { Value = "11", Text = "11" }, new { Value = "12", Text = "12" }, }, "Value", "Text")) <b>:</b> @Html.DropDownListFor(model => item.EnterTimeMinutes, new SelectList(new[] { new { Value = "0", Text = "00" }, new { Value = "15", Text = "15" }, new { Value = "30", Text = "30" }, new { Value = "45", Text = "45" }, }, "Value", "Text")) </div> </div> </div> <div class="col-lg-2"></div> <div class="col-lg-1"></div> <div class="control-group col-12 col-lg-2"> <label class="checkbox"> Billable @Html.CheckBoxFor(model => item.Billable) </label> </div> <div class="col-12 col-lg-2"> Enter Memo: <div class="row"> <div class="col-12"> @Html.TextAreaFor(model => item.Comment) </div> </div>
And here is some code for my controller:
public class TimesheetController : Controller { // // GET: /Timesheet/ public ActionResult Index() { string getBillingCodeUrl =""; //SOME CODE REMOVED FOR LENGTH / READABILITY foreach (var entryItem in timePeriod.TimeEntries[0].EntryCollection) { foreach (var billingItem in billingCodeList.BillingCodes) { if (entryItem.BillingCode == billingItem.Name) { //update record in billingItem with data from entryItem billingItem.Comment = entryItem.Comment; billingItem.Billable = entryItem.Billable; billingItem.TotalHours = entryItem.Hours; } } } return View(billingCodeList); } [HttpPost] public void SubmitTimesheet(BillingCodeList model) { string uri = ""; foreach (var billingCode in model.BillingCodes) { //do stuff with each of these } } } }
and lastly, here is the info that is in the model:
public class BillingCodeList { public List<BillingCodeObj> BillingCodes; } public class BillingCodeObj { public string Name { get; set; } public decimal TotalHours { get; set; } public decimal EnterTimeHours { get; set; } public decimal EnterTimeMinutes { get; set; } public bool Billable { get; set; } public string Comment { get; set; } public BillingCodeObj(string name, decimal hours) { this.Name = name; this.TotalHours = hours; } public BillingCodeObj() { } }
here is a picture of the debug locals when the form is returned..
-
Brandon Knight almost 11 yearsHmm. I think you are right, but the List of billingCodes in the model object I get back is still null.. any ideas? I will edit my question to include your code.
-
Brandon Knight almost 11 yearsOkay, thanks. The first thing did not work, billingCodes object is still null. So I will take some time and inspect the form it returns.
-
Brandon Knight almost 11 yearsI am doing: BillingCodeList billingCodeList = JsonConvert.DeserializeObject<BillingCodeList>(result);
-
Bart Calixto almost 11 yearsif you can post the generated inputs on the html I will happily try to help you.
-
Brandon Knight almost 11 yearsokay I edited my original post and included a picture of the locals also here: link
-
Bart Calixto almost 11 yearsfrom what I see, mvc is interpreting you are not sending a collection but one.
public void SubmitTimesheet(BillingCodeObj item){
<-- this works ? -
Brandon Knight almost 11 yearsYeah you're right that does work. So if I enter the information for more than one billing code at once though it only submits one of them..
-
Bart Calixto almost 11 yearsOne solution will be to change your view so instead of doing a foreach do an EditorFor(m=> m. BillingCodes) and have a EditorTemplate for the BillingCodeObj in EditorTemplates/BillingCodeObj.cshtml or using a partial. Another solution might be using BeginCollectionItem helper blog.stevensanderson.com/2010/01/28/…
-
Brandon Knight almost 11 yearsit just lists the codes like so when i try and make a template and put the code to generate them in there instead of putting buttons? I have never used the editortemplate before so i might be doing something wrong... TrainingPre-Sales SupportTime Off: BereavementTime Off: Floating HolidayTime Off: HolidayTime Off: PTO (Paid Time Off)Create documentation for how to make homescreen icons on all platformsResearch AzureResearch AzureResearch MS Project/TFS Project server integration and link the twoResearch MS Proyecto/TFS integration and link the twoTest TaskWrite up Initial User Stories }
-
Bart Calixto almost 11 yearsFor creating EditorTemplates: 1) Check folder is EditorTemplates and not EditorTemplate 2) FileName should be = class name and html must have a @model directive with this class. In this case I think is BillingCodeObj 3) If any of that doesn't work, take a look at : stackoverflow.com/questions/14655930/…
-
Bart Calixto almost 11 yearsperfect! now controller should receive
(IEnumerable<BillingCodesObj> billingCodes)