Matthias Burger Matthias Burger - 1 month ago 7
Ajax Question

editing a model in more than one view

My target is, to modify a model in more than one view.
Since sometimes my models have many properties I want to modify them in more than one view. Something like:

first page edits 2 properties, second page edits 3 other properties,...

the model looks like this:

public class LoadViewModel
{
public int CurrentPage { get; set; } = -1;
public PageViewModel PageViewModel { get; set; }
}

public class PageViewModel
{
public string Param1 { get; set; }
public string Param2 { get; set; }
public int Param3 { get; set; }
}


my view on the Index-page looks like this:

@model LoadViewModel
@using(Ajax.BeginForm("Load", "Home", new AjaxOptions {UpdateTargetId = "page"}, new {lvm = Model}))
{
<div id="page"></div>
<input type="submit"/>
}


and this is my action:

public ActionResult Load(LoadViewModel lvm = null)
{
if (lvm == null) lvm = new LoadViewModel();
lvm.CurrentPage += 1;
TempData["CurrentPage"] = TempData["CurrentPage"] == null ? 0 : (int)TempData["CurrentPage"] + 1;
if (!partialViewDict.ContainsKey((int) TempData["CurrentPage"]))
TempData["CurrentPage"] = 0;
return PartialView(partialViewDict[(int)TempData["CurrentPage"]], lvm);
}


the pages are just partials that are mapped:

private Dictionary<int, string> partialViewDict = new Dictionary<int, string>
{
{0, "Pages/_Page1"},
{1, "Pages/_Page2"},
{2, "Pages/_Page3"},
};


and designed like this:

@using WebApplication1.Controllers
@model LoadViewModel
@{
TempData["CurrentPage"] = 0;
}

@Html.DisplayNameFor(m => m.PageViewModel.Param1)
@Html.EditorFor(m => m.PageViewModel.Param1)


this is working. When switching to Page2 the model is correctly set, but when hitting the
submit
the value of
Param1
(that I set in Page1) is resetted to
null
and only the values I set in the current partial are correct.

This is Page2:

@using WebApplication1.Controllers
@model LoadViewModel
@{
TempData["CurrentPage"] = 1;
}
@Html.DisplayNameFor(m => m.PageViewModel.Param2)
@Html.EditorFor(m => m.PageViewModel.Param2)


When I add a
@Html.HiddenFor(m => m.PageViewModel.Param1)
into the partial, the value is still set. But I don't want the values to be resetted. I don't want to add an
@Html.HiddenFor
for all properties a set in a previous view. How can I prevent that the values are resetted when hitting
submit
without adding
@Html.HiddenFor
for all not listed attributes? Or is there any other possibility to catch my target?

Answer

There's two pieces to this. First, the post itself, and getting that to validate. For that, each step should have its own view model, containing only the properties it's supposed to modify. This allows you to add all the validation you need without causing other steps to fail. In the end, you'll combine the data from all of these into your entity class or whatever.

Which brings us to the second piece. You need some way of persisting the data from each step. The only data that will exist after a POST is the data that was posted and anything in the session (which includes TempData). You could always create a bunch of hidden fields to store the data from the previous steps, but that can get a little arduous. Most likely, you'll just want to use the session.

TempData is basically a specialized instance of Session, so which you use doesn't really matter. With TempData, you'll need to remember call TempData.Keep() for each of the keys you've set for each step or you'll lose the previous steps on the next request. Session will keep them around for the life of the session, but you should remember to remove the keys at the end with Session.Remove().

Comments