Shaorandra Shaorandra - 3 months ago 7
C# Question

View model parameter is null in HttpPost action method

I am redirecting my viewModel from the HttpPost of View1 to the HttpGet of View2.
This works without problems.
There the user has to accept the terms and agreemens.
This should get changed in the viewModel to true (before it is false).
And then redirect to the HttpPost of view2.

There something goes wrong.
The HttpPost ActionResult of View2 receives the viewModel with all Parameters as NULL (before they were filled)

How can I fix this?

Here is my HttpGet ActionResult for View2:

public ActionResult Verify(QuestionViewModel viewModel)
{
//Anrede in Viewbag
if (viewModelVeri.Per_Salutation == 2)
{
ViewBag.Per_Salutation = "Frau";
}
else
{
ViewBag.Per_Salutation = "Herr";
}

int? per_region_id = viewModelVeri.Per_Region;
int per_region_id_nullable = Convert.ToInt32(per_region_id);

Region region = _repository.GetRegionById(per_region_id_nullable);

QuestionViewModel viewModel2 = new QuestionViewModel()
{
Reg_Name = region.Reg_Name
};

//Regionsname in Viewbag
ViewBag.Reg_Name = viewModel2.Reg_Name;

return View(viewModel);
}


And here's my HttpPost ActionResult for View2:

[HttpPost]
public ActionResult Verify(QuestionViewModel viewModel, string tbButton)
{
//here the ViewModel-Parameters are already NULL


My View:

<div class="panel-body">

@using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
@Html.AntiForgeryToken()
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
@Html.LabelFor(model => model.Per_Salutation, new { @class = "control-label col-sm-1" })
<div class="col-sm-3">
@ViewBag.Per_Salutation
</div>
</div>
</div>
</div>

<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
@Html.LabelFor(model => model.Per_Name_Last, new { @class = "control-label col-sm-1" })
<div class="col-sm-3">
@Html.DisplayFor(model => model.Per_Name_Last, new { @class = "control-label col-sm-1 non-zero-num" })
</div>
@Html.LabelFor(model => model.Per_Name_First, new { @class = "control-label col-sm-1" })
<div class="col-sm-3">
@Html.DisplayFor(model => model.Per_Name_First, new { @class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div

<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
@Html.LabelFor(model => model.Per_EMail, new { @class = "control-label col-sm-1" })
<div class="col-sm-8">
@Html.DisplayFor(model => model.Per_EMail, new { @class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div>

<div class="checkbox">
<input type="checkbox" id="NutzungsbedingungenAngenommen " />
<label for="NutzungsbedingungenAngenommen ">
Ich erkläre mich mit den Nutzungsbedingungen einverstanden.
</label>
</div>

<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}

<script>
$(document).ready(function () {
$(".non-zero-num").val($(this).val() == 0 ? ' ' : $(this).val());
})

$('#verifyform').on('click', '[value="questsend"]', function () {
if ($('#agree').is(':checked')) {
return true;
}
else {
return false;
}
});

</script>


EDIT

Here my QuestionViewModel

public class QuestionViewModel
{
//Other Properties

[Required(ErrorMessage = "Bitte die Nutzungsbedingungen annehmen!")]
public bool NutzungsbedingungenAngenommen { get; set; }
}


My HttpPost Controller for View1:

[HttpPost]
public ActionResult DefaultForm(QuestionViewModel viewModel, string tbButton)
{
if (ModelState.IsValid)
{
try
{
if (tbButton.Equals("questsend"))
{
return RedirectToAction("Verify", viewModel);
}
else if (tbButton.Equals("questupload"))
{
//write to DB
return View(viewModel);
}
else
{
dropdownPopulate(viewModel);
return View("DefaultForm", viewModel);
}
}
catch
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}
else
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}

Answer

The problem is you use Html.DisplayFor to display the property values of viewModel in View2, so the values won't be submitted to the HttpPost method, hence viewModel is null when HttpPost for View2 is executed. Only values in <input> and <select> tags will be submitted.

You can submit the values of viewModel to the HttpPost for View2 by adding Html.HiddenFor inside Html.BeginForm for all properties of viewModel. You should also use Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen) for the checkbox. Something like below should work

@using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.Per_Salutation)
@Html.HiddenFor(m => m.Per_Name_First)
@Html.HiddenFor(m => m.Per_Name_Last)
.... // Html.HiddenFor for the rest of QuestionViewModel properties

....
.... // the rest of your code inside the form tag
.... // remove <input type="checkbox" id="NutzungsbedingungenAngenommen " />

@Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen)
<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}