0

I ran out of options checking why my HttpPost parameter is always null.My Models, View and Controllers are below. In general, I have a model with all details of medication administered to patients (Model 1) below. Then, I created another model with one property which is a list of my first model (Model 2). Model 2 is being passed to the view as shown in the HttpGet action. My HttpPost action accepts a parameter which is a list of Model 1. This list is being passed in my view in the following line which is within the View:

using (Html.BeginForm("ClientChargeInput", "Home", new { @vm = Model.patients.ToList() }, FormMethod.Post, null))

Any feedback?

Model

public class ControlledSubstancesEntity
{
    public string facility { get; set; }
    public string program_x_rrg_value { get; set; }
    public string PATID { get; set; }
    //More properties
}

Model being passed to View

public class ControlledSubsViewModel
{
    public List<ControlledSubstancesEntity> patients { get; set; }
}

HttpGet Controller Action

[HttpGet]
    public ActionResult ClientChargeInput(DateTime adminDate, string Facility)
    {
        ControlledSubsViewModel vm = new ControlledSubsViewModel();
        //Some logic that populates vm
        return View(vm);
    }

View

@model ControlledSubstancesChargeInput.Models.ControlledSubsViewModel

@{
    ViewBag.Title = "ClientChargeInput";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@if (Model != null && Model.patients.Count() > 0)
{
    using (Html.BeginForm("ClientChargeInput", "Home", new { @vm = Model.patients.ToList() }, FormMethod.Post, null))
    {
      <input type="submit" value="Charge Input" id="btnSubmit" class="btn btn-info btn-sm" onclick="PostCharge()" />
        @*Fields are shown*@
         @foreach (var p in Model.patients)
        {
            @Html.HiddenFor(model => p.facility)
            @Html.HiddenFor(model => p.program_x_rrg_code)
            @Html.HiddenFor(model => p.program_x_tx_setting_code)
         }
    }

}
else
{
    @*@Html.Action("ShowReport");*@
}

HttpPost Controller Action

[HttpPost]
    public ActionResult ClientChargeInput(List<ControlledSubstancesEntity> vm)
    {
            //On breakpoint vm is always null
    }
Yoismel
  • 115
  • 1
  • 10
  • You have far too much code here. You need to produce a minimal example that still demonstrates your issue. Please refer to [MCVE]. – mason Sep 06 '18 at 17:13
  • Have you tried using fiddler or some similar tool to see the actual request being sent? – Fix Sep 06 '18 at 17:13
  • @mason Thanks for your feedback, i have shortened the code. – Yoismel Sep 06 '18 at 20:36
  • The issue was my view. I compared my loop and the one by @Win and noticed I was just referencing the fields from the Model. Once i updated the loop everything worked fine. Thanks everyone for your feedback. – Yoismel Sep 06 '18 at 22:01
  • You cannot use a `foreach` loop to generate form controls for a collection (refer the dupe). And your `new { @vm = Model.patients.ToList() }` in the `BeginForm()` makes no sense (look at the html you are generating). But none of this makes any sense. Why in the world would you send a whole lot of data to to the view and then send to all back again unchanged - you just degrading performance. If you need to collection again in the POST method, the just get it for the db –  Sep 06 '18 at 22:03

2 Answers2

1

You can try to use ControlledSubsViewModel instead of List<ControlledSubstancesEntity> class, then you can use vm.patients to do your logic.

because you use ControlledSubsViewModel in the razor view that pass the parameter format will like ControlledSubsViewModel.

[HttpPost]
public ActionResult ClientChargeInput(ControlledSubsViewModel vm)
{
    //vm.patients use this property
}

Because Model.patients is a collection, you can use for loop set input tag (hidden or text) look like this.

@if (Model != null && Model.patients.Count() > 0)
{
    using (Html.BeginForm("ClientChargeInput", "Home",FormMethod.Post))
    {
        <input type="submit" value="Charge Input" id="btnSubmit" class="btn btn-info btn-sm" onclick="PostCharge()" />
        for (int i = 0; i < Model.patients.Count; i++)
        {
            @Html.TextBoxFor(m => Model.patients[i].PATID);
            @Html.TextBoxFor(m => Model.patients[i].facility);
            @Html.TextBoxFor(m => Model.patients[i].program_x_rrg_value);
        }

    }
}
else
{
     @*@Html.Action("ShowReport");*@
}
D-Shih
  • 44,943
  • 6
  • 31
  • 51
  • Just wondering if in the view I will then just pass the model as shown below `code`using (Html.BeginForm("ClientChargeInput", "Home", new { @vm = Model }, FormMethod.Post, null)) – Yoismel Sep 06 '18 at 20:49
  • I made the changes but vm is null – Yoismel Sep 06 '18 at 20:54
  • Why will you want to do that? and you set `new { @vm = Model.patients.ToList() }` in the `BeginForm` method will not set the value. you need to set value in `input` tag. – D-Shih Sep 06 '18 at 20:54
  • Sorry, could you type an example – Yoismel Sep 06 '18 at 21:11
  • @Yoismel I edit my answer you can try it. – D-Shih Sep 06 '18 at 21:22
  • I tried it and when I hover over the parameter in the post action it shows the type (..Model/ControlledSubsViewModel) but the patients list is null – Yoismel Sep 06 '18 at 21:43
  • @Yoismel Are you sure your `Html.BeginForm` set as my answer? because it works in my vs – D-Shih Sep 06 '18 at 21:48
  • 1
    You can try to use `for loop` instead of `foreach` and use lambda by index. – D-Shih Sep 06 '18 at 21:59
  • The issue was the way I was looping in the view. See my loop from the question. Thanks a lot for your feedback – Yoismel Sep 06 '18 at 22:03
0

You still need to create ControlledSubstancesEntity as hidden-fields even if you do not want to display them on the page.

@using (Html.BeginForm("Index", "Home", FormMethod.Post, null))
{
    for (int i = 0; i < Model.patients.Count; i++)
    {
        @Html.HiddenFor(x => Model.patients[i].facility)
        @Html.HiddenFor(x => Model.patients[i].program_x_rrg_value)
        @Html.HiddenFor(x => Model.patients[i].PATID)
    }
    <input type="submit" value="Charge Input" id="btnSubmit" 
      class="btn btn-info btn-sm" onclick="PostCharge()" />
}

Then use ControlledSubsViewModel as a parameter in HttpPost action method.

enter image description here (click on the image to view in full screen)

Win
  • 61,100
  • 13
  • 102
  • 181
  • [Here](https://stackoverflow.com/a/50960218/296861) is the different answer using `PartialView`. – Win Sep 06 '18 at 21:30