asp.net mvc - Multiple forms in MVC view: ModelState applied to all forms -


running trouble multiple forms on single view.

suppose have following viewmodel:

public class changebankaccountviewmodel   {        public ienumerable<bankinfo> bankinfos { get; set; }   }  public class bankinfo   {       [required]       public string bankaccount { get; set; }       public long id { get; set; }   } 

in viewmodel, want bankinfos displayed underneath eachother, inside separate forms each.

to achieve this, i'm using partial view _editbankinfo:

@model bankinfo  @using (html.beginform()) {    @html.hiddenfor(m => m.invoicestructureid)    @html.textboxfor(m => m.ibanaccount)     <button type="submit">update stuff</button> } 

as actual view bankinfo:

foreach(var info in model.bankinfos) {     html.renderpartial("_editbankinfo", info); } 

last, here 2 action methods:

[httpget] public actionresult bankinfo() {     return view(new changebankaccountviewmodel{bankinfos = new [] {new bankinfo...}); } [httppost] public actionresult bankinfo(bankinfo model) {     if(modelstate.isvalid)        modelstate.clear();     return bankinfo(); } 

all of working hunky dory: validation works smooth, posted model gets recognized , validated correctly... however, when page reloads when problem arises. because i'm using same form multiple times, modelstate applied multiple times. when performing update on 1 form, next page load of them have posted values.

is there way prevent happening?

i've tried doing without partial views, screws naming bit (they're unique, serverside modelbinding won't recognize them).

thanks answers.

this bit tricky. here's how can solved. start moving _editbankinfo.cshtml partial editor template ~/views/shared/editortemplates/bankinfo.cshtml looks (notice name , location of template important. should placed inside ~/views/shared/editortemplates , named name of typed used in ienumerable<t> collection property, in case bankinfo.cshtml):

@model bankinfo  <div>     @using (html.beginform())     {         <input type="hidden" name="model.prefix" value="@viewdata.templateinfo.htmlfieldprefix" />         @html.hiddenfor(m => m.id)         @html.textboxfor(m => m.bankaccount)          <button type="submit">update stuff</button>     } </div> 

and in main view rid of foreach loop , replace simple call editorfor helper:

@model changebankaccountviewmodel  @html.editorfor(x => x.bankinfos) 

now each element of bankinfos collection custom editor template rendered. , contrary partial, editor template respects navigational context , generate following markup:

<div>     <form action="/" method="post">             <input type="hidden" name="model.prefix" value="bankinfos[0]" />         <input data-val="true" data-val-number="the field id must number." data-val-required="the id field required." id="bankinfos_0__id" name="bankinfos[0].id" type="hidden" value="1" />         <input data-val="true" data-val-required="the bankaccount field required." id="bankinfos_0__bankaccount" name="bankinfos[0].bankaccount" type="text" value="account 1" />             <button type="submit">update stuff</button>     </form> </div>  <div>     <form action="/" method="post">             <input type="hidden" name="model.prefix" value="bankinfos[1]" />         <input data-val="true" data-val-number="the field id must number." data-val-required="the id field required." id="bankinfos_1__id" name="bankinfos[1].id" type="hidden" value="2" />         <input data-val="true" data-val-required="the bankaccount field required." id="bankinfos_1__bankaccount" name="bankinfos[1].bankaccount" type="text" value="account 2" />             <button type="submit">update stuff</button>     </form> </div>  ... 

now since every field has specific name there no longer conflicts when posting form. notice hidden field named model.prefix explicitly placed inside each form. used custom model binder bankinfo type:

public class bankinfomodelbinder: defaultmodelbinder {     public override object bindmodel(controllercontext controllercontext, modelbindingcontext bindingcontext)     {         bindingcontext.modelname = controllercontext.httpcontext.request.form["model.prefix"];         return base.bindmodel(controllercontext, bindingcontext);     } } 

which registered in application_start:

modelbinders.binders.add(typeof(bankinfo), new bankinfomodelbinder()); 

alright, go. rid of modelstate.clear in controller action no longer need it:

[httpget] public actionresult bankinfo() {     var model = new changebankaccountviewmodel     {         // populated data store         bankinfos = new [] { new bankinfo... },     }     return view(model); }  [httppost] public actionresult bankinfo(bankinfo model) {     if(modelstate.isvalid)     {         // todo: model valid => update value data store         // not call modelstate.clear anymore.        }      return bankinfo(); } 

Comments

Popular posts from this blog

image - ClassNotFoundException when add a prebuilt apk into system.img in android -

I need to import mysql 5.1 to 5.5? -

Java, Hibernate, MySQL - store UTC date-time -