asp.net mvc - Using view models in MvcView scaffolding templates -
i have viewmodel
public class clientindexviewmodel { [key] public int surrogateid { get; set; } // not primary key used in templating public ienumerable<client> clients { get; set; } } and have created new mvcview t4 template called index.cs.t4. when create new view controller , add model class clientindexviewmodel, view template ( index.cshtml ) generated, without properties ienumerable<client>
templated index.cshtml
<table class="table"> <!-- client properties should here .. think --> <tr> <th></th> <!-- empty because dont know doing --> </tr> @foreach (var item in model) { <tr> <td> @html.actionlink("edit", "edit", new { id=item.surrogateid }) | @html.actionlink("details", "details", new { id=item.surrogateid }) | @html.actionlink("delete", "delete", new { id=item.surrogateid }) </td> </tr> } which makes sense when @ template file.
index.cs.t4
<# ienumerable<propertymetadata> properties = modelmetadata.properties; foreach (propertymetadata property in properties) { if (property.scaffold && !property.isprimarykey && !property.isassociation) { #> <# if (property.isassociation && getrelatedmodelmetadata(property) == null) { continue; } #> <th> @html.displaynamefor(model => model.<#= getvalueexpression(property) #>) </th> <# } } #> i able target ienumerable<client> property on viewmodel properties variable, properties enumeration on propertymetadata
i figured might able create method in modelmetadatafunctions.include.t4 file. not sure how , or if should doing that
i found hack makes work. no means sort of ideal use, considering scaffolding code visual studio , not project code doesn't seem bad
firstly . model class, view, entity type want enumerate through. properties client client entity , not viewmodel. model wrong ( of course ) . in template file, index.cs.t4 change control blocks based on viewdatatypeshortname parameter ( found in imports.include.t4 ) . gives me client , because selecting client entity.
so instance in foreach typically display
@foreach (var item in model){ <tr> <td> @html.displayfor(modelitem => <#= "item." + getvalueexpression(property) #>) </td> </tr> } now control adding
@foreach (var item in model.<#= newviewdatatypeshortname #>) // newviewdatatypeshortname created // <# string newviewdatatypeshortname = viewdatatypeshortname + 's'; #> // based on naming convention. which produces in index.cshtml
@foreach (var item in model.clients) { then add @model creating method in modelmetadatafunctions.cs.include.t4
string getviewmodelname(string viewdatatypename,string viewdatatypeshortname,string viewname){ string[] names = viewdatatypename.split(new string[]{"."},stringsplitoptions.none); return names[0] + ".domain.viewmodels." + viewdatatypeshortname + viewname +"viewmodel"; } which called in index.cs.t4
@model <#= getviewmodelname(viewdatatypename,viewdatatypeshortname,viewname) #> and display in index.cshtml
@model taskr.domain.viewmodels.clientindexviewmodel this gives me need. not ideal , relies way heavily on naming conventions not sure hand on developer. instance not scaffold correctly if viewmodel created in main project, because based on separate project data class's. entity type names , view model names have strict convention work ..
please post if have better idea, dont think best practice
Comments
Post a Comment