Reputation: 2055
I know there are a lot of posts on the subject but I cannot find one that helps me do what I want. I know that I will eventually be using Automapper but before I start playing with it, I want to learn how to do things manually. I want to create a ViewModel, populate it with values from my entities by way of a repository and send it to my View. As simple as this sounds, I am stuggling to get it done. I'm using MVC 3, EF 4.3, Database First. I have auto-generated my classes. I'm posting the relevant entities (abbreviated/renamed for this post) and classes, here is what I have so far:
Aggregate Entity: Shipping Header
using System;
using System.Collections.Generic;
namespace My.Models
{
public partial class ShippingHdr
{
public ShippingHdr()
{
this.ShippingLI = new HashSet<ShippingLI>();
}
public int ID { get; set; }
public int ShipToSiteID { get; set; }
public Nullable<System.DateTime> DateShipped { get; set; }
public Nullable<System.DateTime> EstDeliveryDate { get; set; }
public string FromSitePOC { get; set; }
public Nullable<int> ShipperID { get; set; }
public string TrackingNo { get; set; }
public string Comments { get; set;}
public virtual Shippers Shippers { get; set; }
public virtual ICollection<ShippingLI> ShippingLI { get; set; }
}
}
Here is my ViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace My.Models.ViewModels
{
public class ShippingHeaderSummaryVM
{
public int ID { get; set; }
public string Site { get; set; }
public Nullable<System.DateTime> DateShipped { get; set; }
public Nullable<System.DateTime> EstDeliveryDate { get; set; }
public string TrackingNo { get; set; }
public string HeaderComments { get; set; }
public string Shipper { get; set; }
public int NumOrders { get; set; }
public string Site { get; set; }
}
}
Here is a query I got to return the items I want to use to populate my Viewmodel with. I believe the best place for this is in a Repository. I verified it returns the data I want using LinqPad (hence the missing reference to my dbContxt). I just don't know how to get the values from the query to the ViewModel:
var shipments = from h in c.ShippingHdrs
where (h.ShippingLI.Count > 1)
join
e in c.vHr_Employees on h.CreatedBy equals e.ID
join
s in c.Shippers on h.ShipperID equals s.ShipperID
join
r in vAaiomsSites on h.ShipToSiteID equals r.SiteID
select new
{
h.ID,
r.Site,
h.EstDeliveryDate,
h.DateShipped,
h.TrackingNumber,
h.HeaderComments,
e.LastName,
h.ShippingLI.Count,
s.Shipper
};
So what I want to do, again without using Automapper, is to populate the ViewModel with all of the rows from the ShippingHdr entity and pass it to my view.
Here are the filelds that need to be mapped:
ShippingHeaderSummaryVM mapped from shipments
ID = h.ID
Site = r.Site
DateShipped = h.DateShipped
EstDeliveryDate = h.EstDeliveryDate
TrackingNo = h.TrackingNumber
FromSitePOC = e.LastName
NumOrders = h.ShippingLI.Count
Shipper = s.Shipper
HeaderComments = h.HeaderComments
I am stuck here. How do I populate the ViewModel from the query? How then do I then call that action from my controller?
I hope I have given enough information, any help would be appreciated.
Upvotes: 9
Views: 4081
Reputation: 16938
You can also use Linq to do something like this...
shipments.Select(h => new ShippingHeaderSummaryVM(){
ID = h.ID,
Site = r.Site,
DateShipped = h.DateShipped,
EstDeliveryDate = h.EstDeliveryDate,
TrackingNo = h.TrackingNumber,
FromSitePOC = e.LastName,
NumOrders = h.ShippingLI.Count,
Shipper = s.Shipper,
HeaderComments = h.HeaderComments
});
Note that while mapping view models is great for passing to a view, always do it manually when reading from a view model to update your database.
Edit: Thanks for the typo correction:-)
Upvotes: 1
Reputation: 8393
In order to populate a list of shipments based on your view model object you would need to create a mapping method to map from your collection of shipments from your database to a collection of shipments based on your view model:
var model = new List<ShippingHeaderSummaryVM>();
foreach(var h in shipments)
{
var viewModel = new ShippingHeaderSummaryVM
{
ID = h.ID
Site = r.Site
DateShipped = h.DateShipped
EstDeliveryDate = h.EstDeliveryDate
TrackingNo = h.TrackingNumber
FromSitePOC = e.LastName
NumOrders = h.ShippingLI.Count
Shipper = s.Shipper
HeaderComments = h.HeaderComments
}
model.Add(viewModel);
}
return model;
As a side note, this becomes a one liner after you have AutoMapper up and running:
var model = Mapper.Map<IEnumerable<ShippingHdr>, IEnumerable<ShippingHeaderSummaryVM>>(shipments);
While, learning how to do things manually is great. Manually mapping models doesn't really benefit you in any way or form. Go with AutoMapper.
Upvotes: 5