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 templateienumerable
. template part of mvc framework, , generatehtml.editorfor()
each item in enumeration. template generates appropriate editor template for each item in list individually - in case they're instances oforder
, 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
Post a Comment