1

The following code works as I need it to:

 @using (Html.BeginForm("LOLOL", "PATIENT", null))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>PATIENT</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>

        </fieldset>
        <p>
            <input type="submit" value="SUBMIT" />
        </p>
    }  

In LOLOLController:

[HttpPost]
    public IActionResult LOLOL(Patient p) {
        var client = new MongoClient("mongodb://localhost:27017");
        var userId = _userManager.GetUserId(HttpContext.User);
        string db_name = "test" + userId;
        var database = client.GetDatabase(db_name);
        var collection = database.GetCollection<BsonDocument>("patients");
        var filter = Builders<BsonDocument>.Filter.Eq("Name", p.Name.ToString());
        var document = collection.Find(filter).First();
        // I'm cutting short the rest of the code, because when I do something 
 // similar later, "collection.Find(filter).First()" fires an exception, I'll     
// explain..


        return View(p);
    }

I have something equivalent to taking off the fieldset element in the HTML, leaving basically just a button in the "Html.BeginForm", but then the data is clearly not binding properly, which I know because if I just have a button and no data-entry, I click the button and then I get an error saying the data cannot be found from the database. (EDIT: I now have confirmed that this is indeed because the Patient object is not being passed to the controller quite as I expected it to, seems like a brand new Patient object was created upon calling html.beginform ... I thought that maybe the old Patient object was being passed so I did not have to enter all its data members every time we use Html.BeginForm)

In sum, I want to fill out a text box, click a button to load a new page and display the value of that textbox, but have that value also persisted in essentially a session state, so that if I call another Html.BeginForm function and go into a third view, the text from the first view will be displayed in the third view, even though I did not have to type its value in the second view. Hopefully I can repeat this process, and essentially load up the data members of a class with one view per data member.

Devin Andres Salemi
  • 2,158
  • 3
  • 9
  • 20

1 Answers1

1

Make sure you pass the data from the previous view to the new view from your Controller. When you pass it, include @HiddenFor for those properties from the previous view in your new view. That way the new view will keep and then pass the values to your next POST.

@Html.HiddenFor(model => model.PropertyYouPassedAndWantToKeepAndPassAgain

Edit: Here's the logic for using multiple views for one object... as requested.

Model:

public class Patient
{
    string Name { get; set; }
    string Address { get; set; }
    string City { get; set; }
}

Page1 GET:

[HttpGet]
public ActionResult Page1()
{
    Patient patient = new Patient();
    return View("~/Views/Page1.cshtml", patient);
}

Page 1 View... only ask for the name.

@model mysite.Models.Patient

@using (Html.BeginForm("LOLOL", "PATIENT", null))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>PATIENT</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>

        </fieldset>
        <p>
            <input type="submit" value="SUBMIT" />
        </p>
    }

Page1 POST... get the patient and pass it on to the next view...

[HttpPost]
public ActionResult Page1(Patient patient)
{
    if (ModelState.IsValid)
    {
        return View("~/Views/Page2.cshtml", patient); // pass your patient to the second page view with the name
    }
    else
    {
        return View("~/Views/Page1.cshtml", patient);
    }
}

Page2 GET... get the patient from the prior Page1 POST and send it off to the Page2 View.

[HttpGet]
public ActionResult Page2(Patient patient)
    {
        // Receive patient from Page1 post and pass it to new view... includes the name
        return View("~/Views/Page2.cshtml", patient);
    }

Page2 View gets the object... use a HiddenFor to keep the name which you just sent from the GET.

@model mysite.Models.Patient

@using (Html.BeginForm("LOLOL", "PATIENT", null))
{
    @Html.HiddenFor(model => model.Name) @* This will keep the name on your next post *@
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>PATIENT</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Address)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Address)
            @Html.ValidationMessageFor(model => model.Address)
        </div>

    </fieldset>
    <p>
        <input type="submit" value="SUBMIT" />
    </p>
}

Since the HiddenFor holds the Name, it will be passed on your next post. It is there but hidden from the form itself.

[HttpPost]
public ActionResult Page2(Patient patient)
{
    // Because of the HiddenFor, the Name will be passed because it was kept in the view... but hidden from the form itself.
    // It's basically storing it for you to pass again
    if (ModelState.IsValid)
    {
        // Pass object with Name and Address to next controller
        return View("~/Views/Page3.cshtml", patient);
    }
    else
    {
        return View("~/Views/Page2.cshtml", patient);
    }
}

Page2 POST

[HttpPost]
public ActionResult Page2(Patient patient)
{
    // Because of the HiddenFor, the Name will be passed because it was kept in the view... but hidden from the form itself.
    // It's basically storing it for you to pass again
    if (ModelState.IsValid)
    {
        // Pass object with Name and Address to next controller
        return View("~/Views/Page3.cshtml", patient);
    }
    else
    {
        return View("~/Views/Page2.cshtml", patient);
    }
}

Page3 GET

[HttpGet]
public ActionResult Page3(Patient patient)
{
    // Pass patient again... to your next view
    return View("~/Views/Page3.cshtml", patient);
}

Page3 View...

@using (Html.BeginForm("LOLOL", "PATIENT", null))
{
    @Html.HiddenFor(model => model.Name) @* Keep name again for your next post *@
    @Html.HiddenFor(model => model.Address) @* Now we are keeping the address as well *@
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>PATIENT</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.City)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.City)
            @Html.ValidationMessageFor(model => model.City)
        </div>

    </fieldset>
    <p>
        <input type="submit" value="SUBMIT" />
    </p>
} 

And so on and so forth... until you have your model complete and want to do something with it.

justiceorjustus
  • 1,908
  • 1
  • 14
  • 34
  • 1
    Just edited my answer because it seems like you knew what you were doing... I'm guessing it may be the compiler not picking up the changes which has lost me countless hours before. Sometimes it happens if you copy a view and make changes to it or rename it. What does your Error List in Visual Studio say? – justiceorjustus Jun 28 '17 at 15:10
  • I've narrowed down the issue ... When I click the submit button, it creates a new Patient object with only the properties from the form specified, all the other properties are as in the default constructor. I wanted to take a Patient object and specify only one of its data members per View, but when I use html.beginform I lose all the saved data, so I might have to use another strategy.. – Devin Andres Salemi Jun 28 '17 at 15:18
  • 1
    Are you using a different controller per view or the same? I understand what you're trying to achieve, now. Can you post the GETs? Edited my post. Let me know if that does it. – justiceorjustus Jun 28 '17 at 15:28
  • I have to mull your answer over, but seems like it could be what I need... To clarify, someone else said better than me exactly what I am trying to accomplish here: "I am trying to develop a wizard that takes the user from one page to another, "remembering" what the user has input on the first page to the next without saving." – Devin Andres Salemi Jun 28 '17 at 15:34
  • 1
    Yup. You want to use @HiddenFor to keep your model's properties which are not on the form... I'll try to explain the process you want to follow better. – justiceorjustus Jun 28 '17 at 15:35
  • Do I have to keep the same Controller? Originally I wanted to change Controllers at least once I believe, but even if I cannot change Controllers, it should still be a viable strategy – Devin Andres Salemi Jun 28 '17 at 15:36
  • 1
    I would have different controllers for each view, as you have to return a new View from each POST. – justiceorjustus Jun 28 '17 at 15:42
  • 1
    Fantastic, problem solved! Thank you :) Love this site! – Devin Andres Salemi Jun 28 '17 at 15:47
  • 1
    No problem. I added the solution since I already had it typed in notepad++. You may want to revise your question to reflect the final answer so future searchers may find the answer correct for the question. – justiceorjustus Jun 28 '17 at 15:59