c# - Entity Framework Eager Loading - pass data to ViewModel -
in asp.net mvc core app, action method shown below, i'm passing blogs data , related data posts table view return view(await _context.blogs.include(p => p.posts).tolistasync());
since i'm passing data 2 tables, need use viewmodel shown below. question: how can use viewmodel pass related data controller action method test()
view shown below?
in code below i'm getting obvious error:
invalidoperationexception: model item passed viewdatadictionary of type 'system.collections.generic.list'1[asp_core_blogs.models.blog]', viewdatadictionary instance requires model item of type 'system.collections.generic.ilist'1[asp_core_blogs.models.blogpostviewmodels.blogswithrelatedpostsviewmodel]'.
model:
public class bloggingcontext : dbcontext { public bloggingcontext(dbcontextoptions<bloggingcontext> options) : base(options) { } public dbset<blog> blogs { get; set; } public dbset<post> posts { get; set; } } public class blog { public int blogid { get; set; } public string url { get; set; } public list<post> posts { get; set; } } public class post { public int postid { get; set; } public string title { get; set; } public string content { get; set; } public int postyear { get; set; } public int blogid { get; set; } public blog blog { get; set; } }
controller:
[httpget] public async task<iactionresult> test(string returnurl = null) { viewdata["returnurl"] = returnurl; return view(await _context.blogs.include(p => p.posts).tolistasync()); }
viewmodel:
public class blogswithrelatedpostsviewmodel { public int blogid { get; set; } public int postid { get; set; } public string url { get; set; } public string title { get; set; } public string content { get; set; } public int postyear { get; set; } }
view:
@model ilist<asp_core_blogs.models.blogpostviewmodels.blogswithrelatedpostsviewmodel> <div class="row"> <div class="col-md-12"> <form asp-controller="dbrelated" asp-action="entergrantnumbers" asp-route-returnurl="@viewdata["returnurl"]" method="post"> <table class="table"> <thead> <tr> <th></th> <th></th> <th>url</th> <th>title</th> <th>content</th> </tr> </thead> <tbody> @for (int t = 0; t < model.count; t++) { <tr> <td><input type="hidden" asp-for="@model[t].blogid" /></td> <td><input type="hidden" asp-for="@model[t].postid" /></td> <td> <input type="text" asp-for="@model[t].url" style="border:0;" readonly /> <!--not using /*html.displayfor(modelitem => model[t].url)*/ since not submit statename on post. not using <label asp-for=.....> since bootstrap bold text of <label> tag--> </td> <td> <input asp-for="@model[t].title" /> </td> <td> <input asp-for="@model[t].content" /> </td> </tr> } </tbody> </table> <button type="submit" class="btn btn-default">save</button> </form> </div> </div>
you need project query using blogswithrelatedpostsviewmodel
class:
return view( _context.blogs .include(p => p.posts) .selectmany(e=> e.posts.select(p=> new blogswithrelatedpostsviewmodel { blogid= e.blogid, postid=p.postid, url=e.url, ... }) .tolist());
selectmany
extension method allows flatten each projection e.posts
1 sequence, @ end list<blogswithrelatedpostsviewmodel>
Comments
Post a Comment