c# - How do I manually pass data from view to controller? -


i have view form can edited. view rather complicated. form contract. contract name can edited @ top. contract has many ads, , details each of ads can edited. length of form depends on how many ads contract has. have loop in view displays form fields each ad.

furthermore, there fields in model used determine of ad details, shouldn't saved database (yet must appear as, say, dropdowns in view).

also, there model fields don't need appear in view needed in post controller method in order save database (i'm saving manually), must go through view somehow , passed controller. here's model:

public class modcontract {     public int contract_id; // pk; needed     public string contract_name { get; set; } // save     public list<modads> ads { get; set; } }  public class modads {     public int contr_ad_id; // pk; needed      public string name { get; set; } // save      public string print_product_id { get; set; } // used product_name     public string product_name { get; set; } // appear      public string print_ad_option_id { get; set; } // save     public string adv_product { get; set; } // appear      public list<string> editions { get; set; } // save       public double freq_disc { get; set; } // save     public double other_dis_dol { get; set; } // save     public double? other_dis_per { get; set; } // save     public string non_cash_note { get; set; } // save     public double non_cash_cons { get; set; } // save } 

the fields have comment of "save" after them should saved database. ones "appear" must in view not needed in post controller method. ones "needed" needed in post controller method not view.

by way, these model classes don't map one-to-one database tables, they're made several different tables.

as far know don't see how can model binding work this. model that's passed controller has null value ads field of modcontract, example. know how can manually pass want view controller without relying on model binding.

i know might use @html.hiddenfor ids needed in post method not view, reason when tried contract_id , _name, didn't work.

<li data-role="fieldcontain">         <label>contract name</label>         @html.hiddenfor(m => m.contract_id)         @html.editorfor(m => m.contract_name) </li> 

the contract_id returned in post method 0.

let me know if question sounds stupid because impossible or because i'm overcomplicating things, i'm pretty new this.

thanks in advance!

edit

here's view. can't indent right it's readable.

@model oulookmediaweb.models.modcontract  @{     viewbag.title = "modifycontract"; }  @{     var num = 1; }  <h2>modify contract</h2>  @using (html.beginform("modifycontract", "contract", formmethod.post, htmlattributes: new {      data_ajax = "false" })) {     @html.validationsummary();     <ul data-role="listview" data-inset="true">          <li data-role="fieldcontain">             <label>contract name</label>             @html.hiddenfor(m => m.contract_id)             @html.editorfor(m => m.contract_name)         </li>      </ul>      <div>     @foreach (var ad in model.ads)     {         <div id="@num">             <ul data-role="listview" data-inset="true">                 <li data-role="list-divider">@ad.name</li>                 <li data-role="fieldcontain">                     <label><strong>product name</strong></label>                     <div>@ad.product_name</div>                     <div id="@num-drdn0" hidden="true">@html.dropdownlistfor(m => ad.print_product_id, viewdata["products_list"] selectlist)</div>                     <input id="@num-editbutton" type="button" onclick="edit(@num)" value="edit" />                 </li>                  <li data-role="fieldcontain">                     <label><strong>advertising product</strong></label>                     <div>@ad.adv_product</div>                     <div id="@num-drdn1" class="hid">                         <select></select>                     </div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>editions run in:</strong></label>                     @foreach (var ed in ad.editions)                     {                         <div>@ed</div>                     }                     <div id="@num-drdn2" class="hid">                         <select multiple="multiple" data-native-menu="false"></select>                     </div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>frequency discount (%)</strong></label>                     <div>@html.editorfor(m => ad.freq_disc)</div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>other discount ($)</strong></label>                     <div>@html.editorfor(m => ad.other_dis_dol)</div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>other discount (%)</strong></label>                     <div>@html.editorfor(m => ad.other_dis_per)</div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>non cash note</strong></label>                     <div>@html.editorfor(m => ad.non_cash_note)</div>                 </li>                  <li data-role="fieldcontain">                     <label><strong>non cash consideration</strong></label>                     <div>@html.editorfor(m => ad.non_cash_cons)</div>                 </li>              </ul>             @{num++;}         </div>     } </div>  <ul data-role="listview" data-inset="true">     <li data-role="fieldcontain">         <input type="submit" data-theme="e" value="submit" />     </li> </ul>  }  <script type="text/javascript"> var nu; window.onload = function () {     // hide adv prods , editions select     $(".hid select").closest('.ui-select').hide(); }  // called when edit button product clicked function edit(num) {     nu = num;     $("#" + nu + "-drdn0").show(); // show dropdown     $("#" + nu + "-editbutton").closest('.ui-btn').hide(); // hide edit button; '.ui-btn'? wtf?      // remove current product selection div     // remove adv product selection div     // remove editions div       $("#" + nu + "-drdn0 select").change(prodchange); // on select change     $("#" + nu + "-drdn0 select").trigger("change");  // trigger default; happens twice; why? }  // called when magazine selected function prodchange() {     // ajax     var url = '@url.action("getadvprodlist", "contract")' + '?prod_id=' + this.value;      $.getjson(url, null, function (list) {         // adv list dropdown         $("#" + nu + "-drdn1 select").empty(); // remove old stuff         $("#" + nu + "-drdn1 select").closest('.ui-select').show(); // show dropdown         var arr = list.advlist; // array object          $.each(arr, function (ind, val) {             // add each item in list option of select             $("#" + nu + "-drdn1 select").append('<option value=' + val.value + '>' + val.text + '</option>');         });         $("#" + nu + "-drdn1 select").selectmenu('refresh', true); // refresh menu          // ed list         $("#" + nu + "-drdn2 select").empty(); // remove old stuff         $("#" + nu + "-drdn2 select").closest('.ui-select').show(); // show list         var lis = list.edlist; // array object          $.each(lis, function (ind, val) {             // add each item list             $("#" + nu + "-drdn2 select").append('<option value=' + val.value + '>' + val.text + '</option>');         });         $("#" + nu + "-drdn2 select").selectmenu('refresh', true); // refresh menu     }); } 

you have quite few issues there , understandably if have complex form. let me try , summarize problem give best possible solution.

the breakdown

there fields in model...(that) shouldn't saved database (yet must appear as, say, dropdowns in view)

you put these fields in model , treat them read-only. i'll show later how.

there model fields don't need appear in view needed in post controller method in order save database (i'm saving manually)

you don't need that. passing unnecessary data around , introducing on posting. in addition, not allowing users edit them , yet pass client, receive it, , save database.

it exposes security hole in system. example, passing product_name view, don't want edited, save table. can hack value , end product_name never expected.

the fields have comment of "save" after them should saved database.

accept these inputs on form. code shown later.

the ones "appear" must in view not needed in post controller method.

as i've mentioned these should read-only fields on viewmodel, code shown later.

the ones "needed" needed in post controller method not view.

you don't need pass around nor query right away. later database when saving-time comes. pseudo-code shown later.

the proposed solution

at point assume understand mentioned above answering points of question. here relevant codes explanation.

public class contractviewmodel {     // start:read-only fields.      // these fields used read-only     public string product_name { get; set; }     public string adv_product { get; set; }     public ienumerable<selectlistitem> printadoptions { get; set; }     // end:read-only fields.     public inputmodel contract {get;set;}     } // use class capture "all inputs" public class inputmodel {     public int contract_id {get;set;}     public string contract_name { get; set; }     public ienumerable<inputsubmodel> ads {get;set;} }     public class inputsubmodel {     public int contr_ad_id {get;set;}     public string print_ad_option_id {get;set;} // string?     public string name {get;set;} } 

you create "master" viewmodel called contractviewmodel , use on view (of course can have name want). contains fields show information , "input" field capture inputs. flatten representation of entities. "input" field, called inputmodel flatten representation of entities. inputs viewmodel dispersed , persisted properly.

building model

// method creating contract public actionresult create() {     // implement ff methods, whatever method you're using orm, plain ado, etc.     var product = getentityfromyourdb();     // may eagerly load (orm) or query separately, it's     // adoption simple entity structure: id, name     ienumerable<adoption> adoptions = getadoptionsfromdb();       // map entity model     // guessing here "product" has following fields.     // replace accordingly based on entities     var model = new contractviewmodel{         product_name = product.name,         adv_product = product.advproduct,         printadoptions = aoptions.select(x=>               new selectlistitem{ value = x.id, text = x.name })              contract  = getentitiesfromdbandmaptomodel();     };       // @ point have need     // (1) field can show (and not save)     // (2) list of fields can use on drop-down     // (3) input fields, ones post     return view(model); } 

consuming model on view

the example given here solve problem:

as far know don't see how can model binding work this. model that's passed controller has null value ads field of modcontract

never use foreach on collection razor engine cannot write in way can save back. reason elements written have same name , cannot binded (or bound, think right word in english - binded in programming :). use for-loop, see in following code.

@model contractviewmodel  <h2>modify contract</h2> <p>@model.product_name</p> <p>@model.adv_product</p>  @html.hiddenfor(m=>m.contract.contract_id) // reference id saving @html.textboxfor(m=>m.contract.contract_name)  @for(var i=0;i<model.contract.ads.count();i++){     @html.hiddenfor(m=>m.contract.ads[i].contr_ad_id) // reference id saving     @html.textboxfor(m=>m.contract.ads[i].name)     @html.dropdownlistfor(m=>m.contract.ads[i].print_ad_option_id, m.printadoptions) } 

finally, saving need

in example given below notice used bind attribute. tells controller bind , our "input" model , inputmodel. there no need post other values won't need saving or querying, etc. take note if need field, id (e.g. product id) later on use query product product table, because need save name modads table include in inputmodel. have, inputmodel.productid.

[httppost] public actionresult create([bind(prefix = "contract")]inputmodel model) {     // map values flatten model entities     // single entity or complex 1     // i'm sure can determine how     // example:     var modcontract = getcontractfromdb(model.contract_id);     modcontract.contract_name = model.contract_name;     // rest of mapping here } 

conclusion

that closest example can give based on model , trying do. if follow along example, i'm sure solve problem.


Comments

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -