0

I have this code in my controller:

var taxes = db.invoiceTaxes
    .Where(c => c.invoiceId == invoice.invoiceId)
    .GroupBy(row => new { row.TaxId, row.tax, row.percent, row.type })
    .Select(group => new { tax = group.Key.tax, percent = group.Key.percent, sum = group.Sum(s => s.sum), type = group.Key.type });

ViewBag.taxes = taxes.ToList();

If I have this in my view

@foreach (var item in ViewBag.taxes)
{
    @item
}

I get

{ tax = Facturacion.Models.Tax, percent = 16, sum = 31.36, type = False }

But when I have

@foreach (var item in ViewBag.taxes)
{
    @item.percent
}

I get

Object does not contain a definition for percent

How can I show the fields my query returns? (In this case, the value "16")

invoiceTaxes is not my model, it's Invoice

ekad
  • 14,436
  • 26
  • 44
  • 46
Allfarid Morales García
  • 1,455
  • 2
  • 17
  • 27
  • please edit your code to reflect the model name, as indicated in your comment below. and close the question as this is not a problem anymore (??) – Krishna Jul 12 '15 at 21:23

4 Answers4

2

Well, you could (trivial sample, modify and improve as necessary):

//Some dummy class to mock some data to play with
//You don't need this..I just need some data to play with for the sample
public class DummyData
{
    public string InstructorId { get; set; }
    public string Name { get; set; }
    public int Invoice { get; set; }
}

In Controller:

public ActionResult DoDynamic()
{
    //Some data to use only for this sample (you already have some data to query, so you don't need this)
    var data = new List<DummyData>
    {
        new DummyData {Name = "Foo is my name", InstructorId = "Foo 1", Invoice = 1},
        new DummyData {Name = "Bar is my name", InstructorId = "Bar 1", Invoice = 2},
        new DummyData {Name = "Hello is my name", InstructorId = "Foo 2", Invoice = 1},
    };

    var query = data.Where(o => o.Invoice == 1).GroupBy(row => new { row.InstructorId }).Select(group => new { name = group.Key.InstructorId }).ToList();

    //Yeah, we can do dynamic :)
    dynamic foo = new ExpandoObject();
    foo.bar = "Hello from dynamic object";
    if (query.Any())
    {
        var result = "";
        query.ForEach(i => result += i.name + "<br />");
        foo.dyn = result;
    }

    //Lets use ViewBag
    ViewBag.SomeObject = foo;

    //And let's use model too...
    return View(foo);
}

Now for the View:

@model dynamic

<h2>DoDynamic</h2>

<p>View Bag: </p>
<ul>
    <li>@ViewBag.SomeObject.bar</li>
    <li>@Html.Raw(ViewBag.SomeObject.dyn)</li>
</ul>

<p>From dynamic model: </p>
<ul>
    <li>@Model.bar</li>
    <li>@Html.Raw(Model.dyn)</li>
</ul>

Result:

Rendered view

Hope this gets you going...

EdSF
  • 11,753
  • 6
  • 42
  • 83
1

At controller you create anonymous type. Problem is that all properties of anonymous type created with internal accessor. So you can't use it on View.

For more detailed info you can read this answer.

Community
  • 1
  • 1
teo van kot
  • 12,350
  • 10
  • 38
  • 70
0

can you try changing the controler code as below

var taxes = db.invoiceTaxes
    .Where(c => c.invoiceId == invoice.invoiceId)
    .GroupBy(row => new { row.TaxId, row.tax, row.percent, row.type })
    .Select(group => new { tax = group.Key.tax, percent = group.Key.percent, sum = group.Sum(s => s.sum), type = group.Key.type });

return View(taxes.ToList()); // Changed here from Viewbag to View(model)

In view

@model IEnumerable<Facturacion.Models.Tax>
//Some code here to define UI etc
@foreach (var item in Model)
{
    <td>
        @Html.DisplayFor(modelItem => item.percent)
    </td>

}
Krishna
  • 2,451
  • 1
  • 26
  • 31
0

You should create a new viewmodel to hold the values (if you don't have one already).

then use

 .Select(group => new InvoiceTaxViewModel { 
    tax = group.Key.tax, 
    percent = group.Key.percent, 
    sum = group.Sum(s => s.sum), 
    type = group.Key.type });

Then in your view you should cast the ViewBag object back to a List<Of Model>

@foreach (var item in (List<InvoiceTaxViewModel>)ViewBag.taxes)
{
    @item.percent
}

I would probably create a new object in the view just before this

@{
    var invoiceTaxList = ViewBag.taxes as List<InvoiceTaxViewModel>;
}

@foreach (var item in invoiceTaxList)
{
    @item.percent
}
user5103147
  • 221
  • 1
  • 6