asp.net mvc - MVC can't override EditorTemplate name when used in EditorFor for child object -


i trying use editortemplate display child collection in table in parent’s view. problem have run seems work if template named same child’s class. when attempt use template different name, , pass name templatename argument editorfor,i runtime error. hoping use different child editortemplates different purposes same child collection. here abbreviated example:

models:

public class customer {   int id { get; set; }   public string name { get; set; }    public list<order> orders { get; set; } } public class order {     public int id { get; set; }     public datetime orderdate { get; set; }     public decimal amount { get; set; }      public customer customer { get; set; } } 

customer controller index() method:

public actionresult index() {   customer customer = new customer() {id = 1, name = "acme corp.", orders = new list<order>()};   customer.orders.add(new order() {id = 1, orderdate = datetime.now, amount = 100m});   customer.orders.add(new order() { id = 2, orderdate = datetime.now, amount = 200m });   return view(customer); } 

customer index.cshtml view:

@model templatetest.customer  @{   layout = null; }  <!doctype html>  <html> <head>   <meta name="viewport" content="width=device-width" />   <title>customer</title> </head> <body>   <div>       @html.editorfor(model=>model.name)        <table>       <thead>           <tr>               <th>order id</th>               <th>order date</th>               <th>amount</th>           </tr>       </thead>           @html.editorfor(model=>model.orders)       </table>    </div> </body> </html> 

order.cshmtl template in views/shared/editortemplates (added “color” verify using template):

@model templatetest.order  <tr>   <td>@html.displayfor(model=>model.id)</td>   <td style="color:blue">@html.editorfor(model=>model.orderdate)</td>   <td>@html.editorfor(model=>model.amount)</td> </tr> 

this works fine. if rename editortemplate “orderlist.cshtml” , change child editorfor line to

@html.editorfor(model=>model.orders, "orderlist") 

when run again exception:

“the model item passed dictionary of type 'system.collections.generic.list`1[templatetest.order]', dictionary requires model item of type 'templatetest.order'.”

any idea why editorfor doesn’t use template “orderlist” specified in “templatename" argument? otherwise, argument for?

tl;dr > named templates don't work collections, use foreach loop work around - see below extensive details why, , example.


you said:

any idea why editorfor doesn’t use template “orderlist” specified in “templatename" argument? otherwise, argument for?

editorfor using the template orderlist specified -- you've stumbled on confusing. research turned lot of hints found real nuts-and-bolts details in post: problem mvc editorfor named template

in short, happening default case works:@html.editorfor(model=>model.orders) calling mvc default template in interim convention, not obvious @ all.

try thinking of way:

in working version passing in type list<order> reference model.orders (many orders) template specified model of order (single, not many).

interesting. why work? @ first glance seems should not work. work because of happens behind scenes.

paraphrased above mentioned post:

when use @html.editorfor(c => c.orders) mvc convention chooses the default template ienumerable. template part of mvc framework, , generate html.editorfor() each item in enumeration. template generates appropriate editor template for each item in list individually - in case they're instances of order, so, order template used each item.

that's magic, , handy, because happens convention , hidden us, source of confusion in opinion.

now when try same thing using named template explicitly setting editorfor use particular editor template orderlist, end editor template being passed whole enumeration -- , source of error posted.

in other words failing case manages skip on 'magic' part of working case , why fails. but, semantically looks , sound, right? there's confusion.

working case:

your call                                default mvc template      template @html.editorfor( model => model.orders)  ienumerable template      order template 

failing case:

your call                                           template @html.editorfor(model=>model.orders, "orderlist")   orderlist template       error!!! 

there's number of ways make error go away, many of them problematic because cause html controls rendered in way prevents being able address individual controls index on post. uhhg. (note: working case render html correctly expected)

to html controls rendered properly, seems must use regular for loop (not foreach) , pass each of individual order objects custom template (which i've called ordereditortemplatedefault).

@for (int = 0; < model.orders.count ; i++)  {     @html.editorfor(c => model.orders[i], "ordereditortemplatedefault") }  

part of question indicated:

i hoping use different child editortemplates different purposes same child collection.

you introducing condition inside loop , choosing alternate template there (either entire list or on order-by-order basis, depends on how write condition)

@for (int = 0; < model.orders.count ; i++) {     if (somecondition) {         @html.editorfor(c => model.orders[i], "ordereditortemplatedefault")     } else {         @html.editorfor(c => model.orders[i], "ordereditortemplatealternate")     } }  

sorry verbose. hope helps.


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -