c# - Handling array's in post back data - MVC3 -
i'm current webforms developer trying move mvc. i'm super excited mvc , i'm have fun i'm running weird issue. i'm trying create advanced editor "widget". i've posted code below.
everything appears work fine when add first 4-5 items problem occurs when delete 2nd item. here visual example.
first add 4 values.
but problem occurs when delete 2nd value. end this...
what cannot seem understand why property act different between 2 following lines of code.
@model.values[i] @html.textboxfor(m => m.values[i])
my guess @model , (m =>m) not reference same object?
here widget class.
public class widget { #region constructor public widget() { id = 0; name = string.empty; values = new list<string>(); } #endregion #region properties [required] [display(name = "id")] public int id { get; set; } [required] [display(name = "name")] public string name { get; set; } [required] [display(name = "values")] public list<string> values { get; set; } #endregion }
my controller looks this.
public viewresult editwidget(int id) { return view(_widgets.getwidgetbyid(id)); } [httppost] public actionresult editwidget(widget widget) { if (!tryupdatemodel(widget)) { viewbag.message = "error..."; return view(widget); } if (request.form["addwidgetvalue"] != null) { widget.values.add(request.form["textboxwidgetvalue"]); return view("editwidget", widget); } if (request.form["deletewidgetvalue"] != null) { widget.values.remove(request.form["listboxwidgetvalues"]); return view("editwidget", widget); } _widgets.updatewidget(widget); _widgets.save(); return redirecttoaction("index"); }
and view.
@model mvctestapplication.models.widget @{ viewbag.title = "editwidget"; } <h2>editwidget</h2> <script src="@url.content("~/scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@url.content("~/scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (html.beginform()) { @html.validationsummary(true) <fieldset> <legend>widget</legend> @html.hiddenfor(model => model.id) <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> @for (var = 0; < model.values.count; i++) { @model.values[i] @html.textboxfor(m => m.values[i]) @html.hiddenfor(m => m.values[i]) <br /> } @html.listbox("listboxwidgetvalues", new selectlist(model.values), new { style = "width: 100%" })<br /> @html.textbox("textboxwidgetvalue", string.empty, new { style = "width: 100%" }) <input type="submit" value="add" id="addwidgetvalue" name="addwidgetvalue" class="submitbutton" /> <input type="submit" value="delete" id="deletewidgetvalue" name="deletewidgetvalue" class="submitbutton" /> <p> <input type="submit" value="save" /> </p> </fieldset> } <div> @html.actionlink("back list", "index") </div>
the reason happening because html helpers first @ modelstate posted values when binding , in model. means if inside post controller action try modify value , same value part of initial post request html helper use initial value , not 1 modified.
for example in editwidget action doing this:
if (request.form["deletewidgetvalue"] != null) { widget.values.remove(request.form["listboxwidgetvalues"]); return view("editwidget", widget); }
you should remove posted value model state:
if (request.form["deletewidgetvalue"] != null) { var itemtoremove = request.form["listboxwidgetvalues"]; var index = widget.values.indexof(itemtoremove); modelstate.remove("values[" + index + "]"); widget.values.remove(itemtoremove); return view("editwidget", widget); }
so post request contained:
values[0] = 1 values[1] = 2 values[2] = 3 values[3] = 4
inside post action removed example second item should remove model state or textboxfor helper still use old one.
you may find following blog post useful. it's asp.net mvc 2 webforms trivial adapt razor.
Comments
Post a Comment