简体   繁体   中英

How do I retain object property values between more than one strongly typed view?

  • I have one view model called ExampleViewModel .
  • I have one controller called ExampleController
  • I have two views called Page1 and Page2 .

Both views are strongly typed with ExampleViewModel .

ExampleViewModel contains two properties, Name and Age .

  • Page1 captures data for the property Name .
  • Page2 captures data for the property Age .

When I visit page1 , I fill in the textbox for the Name property and hit a 'Next' button which will post the data to the controller.

When debugging you can see the data is posted OK. The data sent back to the post function is a ExampleViewModel object. Then I pass that same object to into Page2 .

When I then visit page2 , I fill in the textbox for the Age property and hit a Back button which will post the data to the controller.

The problem here is when you look into the ExampleViewModel object that was posted back, the Name property value which was set in Page1 is now lost, and only Page2 data is submitted ( Age property).

How do I keep property values of the same object that are passed between views?

ExampleViewModel

public class ExampleViewModel
{
    public string Name { get; set; }
    public int Age { get; set; }
}

ExampleController

public class ExampleController : Controller
{
    [HttpPost]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult PostMethod (ExampleViewModel formData, FormCollection form, string command)
    {
        string newView = "";
        string newController = "";

        Session["formData"] = formData;

        if (command.ToLower() == "back")
        {
            newView = form["PreviousAction"];
            newController = form["PreviousController"];
        }
        else if (command.ToLower() == "next")
        {
            newView = form["NextAction"];
            newController = form["NextController"];
        }

        return RedirectToAction(newView, newController);
    }

    public ActionResult Page1()
    {
        return GetView();
    }

    public ActionResult Page2()
    {
        return GetView();
    }

    private ViewResult GetView()
    {
        ExampleViewModel formData = (ExampleViewModel)Session["formData"];

        if (formData != null)
        {
            return View(formData);
        }
        else
        {
            return View();
        }
    }
}

Page 1 View

@model ExampleProject.ViewModels.ExampleViewModel

@using (Html.BeginForm("PostMethod", "Example", FormMethod.Post))
{
   @Html.Label("Your name")
   @Html.TextBoxFor(m => m.Name)

   <input id="ButtonNext" type="submit" name="Command" value="Next" />

   @Html.Hidden("nextaction", "page2")
   @Html.Hidden("nextcontroller", "example")
}   

Page 2 View

@model ExampleProject.ViewModels.ExampleViewModel

@using (Html.BeginForm("PostMethod", "Example", FormMethod.Post))
{
   @Html.Label("Age")
   @Html.TextBoxFor(m => m.Age)

   <input id="ButtonBack" type="submit" name="Command" value="Back" />

   @Html.Hidden("previousaction", "page1")
   @Html.Hidden("previouscontroller", "example")
}

This is because when you post back Page2, you no longer have Name set as it is not persisted anywhere.

One way to persist this is, in your Page2 view, you also add a HiddenField for your name property, so that when you post your Page2 back to the server, the Name field will still be bound.

@model ExampleProject.ViewModels.ExampleViewModel

@using (Html.BeginForm("PostMethod", "Example", FormMethod.Post))
{
  @Html.Label("Age")
  @Html.TextBoxFor(m => m.Age)
  @Html.HiddenFor(m => m.Name)

  <input id="ButtonBack" type="submit" name="Command" value="Back" />

  @Html.Hidden("previousaction", "page1")
  @Html.Hidden("previouscontroller", "example")
}

In Page1 you should send back the value of Age to the controller via a hidden input:

@using (Html.BeginForm("PostMethod", "Example", FormMethod.Post))
{
   @Html.Label("Your name")
   @Html.TextBoxFor(m => m.Name)
   @Html.HiddenFor(m => m.Age)

   <input id="ButtonNext" type="submit" name="Command" value="Next" />

   @Html.Hidden("nextaction", "page2")
   @Html.Hidden("nextcontroller", "example")
}

and in Page2 do same thing for Name :

@model ExampleProject.ViewModels.ExampleViewModel

@using (Html.BeginForm("PostMethod", "Example", FormMethod.Post))
{
   @Html.Label("Age")
   @Html.TextBoxFor(m => m.Age)
   @Html.HiddenFor(m => m.Name)

   <input id="ButtonBack" type="submit" name="Command" value="Back" />

   @Html.Hidden("previousaction", "page1")
   @Html.Hidden("previouscontroller", "example")
}

Right way to do it is

I can think of two easy ways.

i) Use Wizard kind of Clientside javascript control(or Jquery,Angularjs etc) and postback on the last Submit(Step) or Just Show/Hide different sections of page on browser through javascript and Submit (postback) as Final Step.

Here is an example Link

OR

ii) Save the Object on every postback.

If you are saving these values, I mean saving 'Name' on Page1 Postback, then on page2 Postback you should just retrieve the saved object from db and just set 'age' to the Model and save it back to db.

Only update the values of Model that user is allowed to update through each Postback.

I would not recommend to saving this object in session.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM