Question

In addition to the detail rows in my view, I would like to show some aggregate data like "count" and "sum". I have a picking lists table, and apart from displaying the list lines organized by SKU, I would like to show a total per SKU.

My PickingList model looks like the following:

public partial class PickingList
{
    public int Id { get; set; }
    [ForeignKey("List_Header")]
    public int TransID { get; set; }
    public string SKU { get; set; }
    public int ColorId { get; set; }
    public double Qty { get; set; }
    public decimal Price { get; set; }

    public virtual List_Header List_Header { get; set; }
}

The controller, where I pass the TransID to the list is:

    public ActionResult ListShipment(int transid)
    {
        var mylist = db.PickingLists.Where(p => p.TransID == transid);
        mylist = mylist.OrderBy(p => p.Id);
        return View(mylist.ToList());
    }

And, finally, what I would like to achieve is something like this:

SKU           Qty              Color

61009         12 pieces
               3               Blue
               5               Red
               4               Green

61011         10 pieces
               6               Blue
               4               Red

I've tried the following View code block, but can't figure out where to place the aggregate (sum) function:

@foreach (var group in Model.GroupBy(item => item.SKU))
                {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => group.Key)
                        </td>
                   </tr>
                    foreach (var item in group.OrderBy(o => o.Id))
                    {
                        <tr>
                            <td></td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Qty)
                            </td>
                            .........
                            .........
                            .........

How could I achieve that?

Was it helpful?

Solution

I am not sure if I understood your requirement completely however I think you are trying to perform some aggregates on the data you have received on the client side. If that is the case you can use

Linqjs

Its pretty awesome and gives you the ability to use .Net methods at client side code.

Another way is, define a ViewModel and add QtySum and LineCount property. Compute that at server side code and return the ViewModel to client. Client side code will use these values to render UI.

Update 1:

Looking at more information on what you want to achieve I am sure you definitely want to go with defining ViewModel approach. I prefer that as it give me more control as I am writing server side code and has all the abilities (.net methods). Second I prefer to keep view as dumb and lightweight as possible.

In you current scenario, I would define view model as below (consider this example for guidance and modify as per your need):

public class PickingListViewModel
{
    public int Id { get; set; }
    public int TransID { get; set; }
    public PickingListSkuViewModel SkuGroupModel { get; set; }
}

public class PickingListSkuViewModel
{
    public string SKU { get; set; }
    public IEnumerable<PickingListItemViewModel> GroupItems { get; set; }
}

public class PickingListItemViewModel
{
    public int ColorId { get; set; }
    public string Color { get; set; }
    public double Qty { get; set; }
    public decimal Price { get; set; }
}

Now at controller I can fill the view model like so (again note that preferred approach is to fetch the data from business or data layer):

public ActionResult Index()
{
    ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

    // Read this data from business layer
    var group1 = new PickingListSkuViewModel
    {
        SKU = "61009",
        GroupItems = new List<PickingListItemViewModel>
        {
            new PickingListItemViewModel
            {
                Color = "Blue",
                Qty = 12,
                Price = (decimal) 2.5
            },
            new PickingListItemViewModel
            {
                Color = "Red",
                Qty = 3,
                Price = (decimal) 4.5
            }
            ,
            new PickingListItemViewModel
            {
                Color = "Green",
                Qty = 4,
                Price = (decimal) 1.5
            }
        }
    };

    var group2 = new PickingListSkuViewModel
    {
        SKU = "61011",
        GroupItems = new List<PickingListItemViewModel>
        {
            new PickingListItemViewModel
            {
                Color = "Blue",
                Qty = 12,
                Price = (decimal) 2.5
            },
            new PickingListItemViewModel
            {
                Color = "Red",
                Qty = 3,
                Price = (decimal) 4.5
            }
            ,
            new PickingListItemViewModel
            {
                Color = "Green",
                Qty = 4,
                Price = (decimal) 1.5
            }
        }
    };

    var model = new List<PickingListViewModel>
    {
        new PickingListViewModel
        {
            Id = 1,
            TransID = 101,
            SkuGroupModel = group1
        },
        new PickingListViewModel
        {
            Id = 2,
            TransID = 102,
            SkuGroupModel = group2
        }
    };

    return View(model);
}

Controller should just initialize the model and return it to appropriate view.

I have not included view code as I believe you are comfortable with it. As hint you now have all the information per group, just write rendering code. You can add sum or count or any other aggregate into PickingListItemViewModel or simple computation can be performed on view code e.g. TotalPrice = Quantity * Price

Let me know if you have any follow up question. Hope this helps.

OTHER TIPS

As SBirthare suggests, I think you should probably create a view model and move the some of the work there. However, to answer you question, maybe you may be looking for the following:

<tr>
  <td>
    @Html.DisplayFor(modelItem => group.Key)
  </td>
  <td>
    @Html.DisplayFor(modelItem => group.Sum(item => item.Qty))
    <span> pieces</span>
  </td>
</tr>

If I have misunderstood your question, let me know.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top