0

I decided to post a new question rather then add to the existing because it is not the same issue. I followed the comment to the other question to create a ViewModel.

I have not had, up to this point, had to list from a ViewModel. I did search online to see if I could find an example but all I found was; How to create a list in a ViewModel, which I already know how to do.

I have a ViewModel below. I am not sure that it is structured properly or not but the controller is returning count = 0

Controller:

    public ActionResult Index()
    {
        List<AccountingViewModels> list = new List<AccountingViewModels>();
        return View(list);
    }

The View Has This: @model IEnumerable<BestenEquipment.Models.AccountingViewModels>

I did try to do this @model List<BestenEquipment.Models.AccountingViewModels>

But got an Error 'List<AccountingViewModels>' does not contain a definition for 'Description' and no extension method 'Description' accepting a first argument of type 'List<AccountingViewModels>' could be found (are you missing a using directive or an assembly reference?)

Controller is still count = 0

The IEnumerable does not error out it just gives me an empty table. So I am thinking the IEnumerable is the way to go. I just need to fix the controller.

If someone could point me in the right direction or tell me what I have wrong in my Controller it would help a great deal.

Here is the ViewModel:

public class AccountingViewModels
{
    [Key]
    public Guid TransactionId { get; set; }
    public string Description { get; set; }
    [Display(Name = "Company")]
    public int? CompanyId { get; set; }
    [Display(Name = "Vendor")]
    public Guid? VendorId { get; set; }
    [Display(Name = "Rec Chk #")]
    public string InCheckNumber { get; set; }
    [Display(Name = "Sent Chk #")]
    public string OutCheckNumber { get; set; }
    [Display(Name = "Invoice #")]
    public string InvoiceNumber { get; set; }
    [Display(Name = "PO #")]
    public string PurchaseOrderNumber { get; set; }
    [Display(Name = "Ledger Acct")]
    public Guid LedgerAccountId { get; set; }
    [Display(Name = "Credit")]
    public decimal? DebitAmount { get; set; }
    [Display(Name = "Debit")]
    public decimal? CreditAmount { get; set; }
    [Display(Name = "Transaction")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = false)]
    public DateTime TransactionDate { get; set; }
    [Display(Name = "Modified By")]
    public string ModifiedBy { get; set; }
    [Display(Name = "Modified")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = false)]
    public DateTime? ModifiedDate { get; set; }
    public string SavedDocument { get; set; }
    [Display(Name = "Created")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = false)]
    public DateTime CreatedDate { get; set; }
    [Display(Name = "Created By")]
    public string CreatedBy { get; set; }
    public bool IsCredit { get; set; }
    public bool IsDebit { get; set; }
    public Guid Type { get; set; }

    [ForeignKey("LedgerAccountId")]
    public LedgerAccount LedgerAccount { get; set; }
    [ForeignKey("CompanyId")]
    public CompanyNames Company { get; set; }
    [ForeignKey("VendorId")]
    public Vendors Vendor { get; set; }
}

This is most likely a simple fix, I just need a nudge..

Using the db model is like this: return View(db.Transaction.ToList());

I need to do the same but with a ViewModel..

Thanks for your help!

Thanks

UPDATE:

Here is the link to my Original problem and was told to create a viewModel.. Original Issue

UPDATE:

Adding View:

@model List<BestenEquipment.Models.AccountingViewModels>
@{
   Layout = "~/Views/Shared/_DashboardLayout.cshtml";
}


@section ScriptsOrCss
{
    @Html.Action("DataTableCssJs", "Layout")
}
@Html.ValidationSummary(true, "", new { @class = "text-danger" })

<section class="content-header">
<h1>
    Overview List
    <small> Transactions </small>
</h1>
</section>
<section class="content">
<!-- Small boxes (Stat box) -->
<div class="row">
    <div class="col-md-12">
        @if (ViewBag.Create == true)
        {
            <div class="box box-solid box-primary">
                <div class="box-body">
                    <!-- Split button -->
                    <div class="margin">
                        <div class="btn-group">
                            @Ajax.ModalDialogActionLink("Create Quick", "Create", "Create ", "btn btn-info btn-sm")
                        </div>
                        <div class="btn-group">
                            <a href="~/Tranaction/Create" class="btn btn-warning btn-sm">Create Full</a>
                        </div>
                    </div>
                    <!-- flat split buttons -->
                </div><!-- /.box-body -->
            </div>
        }

        <div class="box box-primary">
            <div class="box-header">
                <h3 class="box-title">Orders</h3>
            </div><!-- /.box-header -->
            <div class="box-body table-responsive">
                <table class="table table-striped table-hover table-bordered" id="TransactionListTable">
                    <thead>
                        <tr>
                            <th>
                                @Html.DisplayNameFor(model => model.Description)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.Company.CompanyName)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.Vendor.Name)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.InCheckNumber)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.OutCheckNumber)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.InvoiceNumber)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.PurchaseOrderNumber)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.LedgerAccountId)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.DebitAmount)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.CreditAmount)
                            </th>
                            <th>
                                @Html.DisplayNameFor(model => model.TransactionDate)
                            </th>
                            <th>
                                CRUD
                            </th>
                            <th>
                                Actions
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var item in Model.Items)
                        {
                        <tr>
                            <td>
                                @Html.DisplayFor(modelItem => item.Description)
                            </td>
                            <td>
                                @if (item.CompanyId != null)
                                {
                                    @Html.DisplayFor(modelItem => item.Company.CompanyName)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }

                            </td>
                            <td>
                                @if (item.VendorId != null)
                                {
                                    @Html.DisplayFor(modelItem => item.Vendor.Name)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }

                            </td>
                            <td>
                                @if (item.InCheckNumber != null)
                                {
                                    @Html.DisplayFor(modelItem => item.InCheckNumber)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }
                            </td>
                            <td>
                                @if (item.OutCheckNumber != null)
                                {
                                    @Html.DisplayFor(modelItem => item.OutCheckNumber)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }

                            </td>
                            <td>
                                @if (item.InvoiceNumber != null)
                                {
                                    @Html.DisplayFor(modelItem => item.InvoiceNumber)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }

                            </td>
                            <td>
                                @if (item.PurchaseOrderNumber != null)
                                {
                                    @Html.DisplayFor(modelItem => item.PurchaseOrderNumber)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.LedgerAccount.Title)
                            </td>
                            <td>
                                @if (item.IsDebit == true)
                                {
                                    @Html.DisplayFor(modelItem => item.DebitAmount)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }

                            </td>
                            <td>
                                @if (item.IsCredit == true)
                                {
                                    @Html.DisplayFor(modelItem => item.CreditAmount)
                                }
                                else
                                {
                                    <b>N/A</b>
                                }
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.TransactionDate)
                            </td>
                            <td>

                                @if (ViewBag.Edit == true)
                                {
                                    @Ajax.ModalDialogActionLink("Edit", "Edit", "Edit", "btn btn-warning btn-sm", new { id = item.TransactionId })
                                }

                                @if (ViewBag.Read == true)
                                {
                                    @Ajax.ModalDialogActionLink("Details", "Details", "Transaction Details", "btn btn-info btn-sm", new { id = item.TransactionId })
                                }

                                @if (ViewBag.Delete == true)
                                {
                                    @Ajax.ActionLink("Delete", "Delete", "Tranaction", new { id = item.TransactionId },
                                             new AjaxOptions()
                                             {
                                                 HttpMethod = "Delete",
                                                 Confirm = "Are you sure you want to delete " + item.Description + "Transaction",
                                             }, new { @class = "btn btn-danger btn-sm Delete" })
                                }
                            </td>
                            <td>
                            
                            </td>
                        </tr>

                        }
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>
8
  • 1
    You haven't shared your View, but it looks like you are saying Model.Description in your View when you should be saying something like foreach (var item in Model) { item.Description }. Commented Jan 8, 2021 at 3:15
  • @Noah I can add my View, however Controller is not populating anything and here is from my view ` @Html.DisplayFor(modelItem => item.Description)` Commented Jan 8, 2021 at 3:19
  • I think a model cannot be IEnumerable or List. It has to be a plain object. You can create model class and put this Ienumerable as a property in the Model. Commented Jan 8, 2021 at 3:20
  • @Sreenath I think I have done that before but not what I need. The original problem i had was displaying a list with a couple of the columns from another table in another database. However i was told to create a viewModel instead. The columns showed up empty. Original question was added to the Question Above. Commented Jan 8, 2021 at 3:25
  • The predicate you wrote doesn't look quite right, because you have modelItem on one side and item on the other. Anyway, since your model is a collection of AccountingViewModelss, you are indeed trying to reference the Description property of the collection, which does not exist. It's a property of each item in the collection. That's the cause of that error. It's nothing to do with the controller or the emptiness of the collection. Commented Jan 8, 2021 at 3:30

3 Answers 3

1

I replicated your error. Try this.

Instead of this one:

@model List<BestenEquipment.Models.AccountingViewModels>

Use this:

@model IEnumerable<BestenEquipment.Models.AccountingViewModels>

Then lastly, remove the Items word on your foreach loop, it should be:

@foreach (var item in Model)
Sign up to request clarification or add additional context in comments.

3 Comments

Actually last night I found why it was giving me that error.. It was not the loop it was the column headers: @Html.DisplayNameFor(model => model.Description) and Description is the first header..
I am still not able to populate this view with the answers I have been given. I am maybe leaning on using a MSSQL View to populate the view instead. Seems like that is an easier option as I have not been given a clear answer to do it in the view and model itself..
I tried that one before as well. I have created a SQL View Once I Get it put in place I will share it in an answer.. After all the database is supposed to do the work anyway right!
0
Public class AcctModel
{
public IEnumerable<AccountingViewModels> Items {get; set;}
}

In view.cshtml

foreach(var item in Model.Items)
{
// Your code here
}

1 Comment

Tried this with just an empty Controller 'return View();' But am getting same error: ''List<AccountingViewModels>' does not contain a definition for 'Description' and no extension method 'Description' accepting a first argument of type 'List<AccountingViewModels>' could be found (are you missing a using directive or an assembly reference?)'
0

I have found that when you are just listing records it is easier to use SQL Views. There isn't any creating or editing with this so just to populate what you need is easier that way. The Databases job is to do the work so why not let it!

Here is what I did incase someone needs something like this or is looking for a cleaner way to do it. Remember I needed Joins from tables in 2 separate databases. Creating a View in the same database is easier, you just select the tables and then the fields you want.

First Create the View, in my case I needed to do the query with aliases and did not use the GUI.

SQL:

SELECT        t.TransactionId, t.Description, t.InCheckNumber, t.OutCheckNumber, t.InvoiceNumber, t.PurchaseOrderNumber, la.Title, t.DebitAmount, t.CreditAmount, t.TransactionDate, t.SavedDocument, t.CreatedDate, t.CreatedBy, tt.Type, 
                     cn.CompanyName, v.Name
FROM            dbo.LedgerAccount AS la INNER JOIN
                     dbo.[Transaction] AS t ON la.LedgerAccountId = t.LedgerAccountId 
INNER JOIN
                     dbo.TransactionType AS tt ON t.Type = tt.TypeId INNER JOIN
                     OtherDBName.dbo.CompanyNames AS cn ON t.CompanyId = 
cn.CompanyId LEFT OUTER JOIN
                     OtherDbName.dbo.Vendors AS v ON t.VendorId = v.VendorId

I called the Transaction table t the Type table as tt and when you are referencing another database you have to use dbname.schema.table.column These I gave the names cn for CompanyNames table and v for Vendors table. In my particular case I will not always have a Vendor name in every record so you do a LEFT OUTER JOIN
Once this is created you can now go back to your project and create the Entity.

In Your Context you will create this as if it is just another table. With the exception of not mapping it. There is no need to. We are not using this for CRUD actions. I called the view TransactionsView:

public class AccountingEntities : DbContext
{
    public AccountingEntities() : base("AccountingConnection")
    {
    }

    [NotMapped]
    public IDbSet<TransactionsView> TransactionsView { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Usings:

using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.ComponentModel.DataAnnotations.Schema;

Then create the Model TranactionsView:

using System;
using System.ComponentModel.DataAnnotations;

namespace YourProject.AccountingDTO.Entities
{
public class TransactionsView
{
    [Key]
    public Guid TransactionId { get; set; }
    [Display(Name = "Desc")]
    public string Description { get; set; }
    [Display(Name = "Company")]
    public string CompanyName { get; set; }
    [Display(Name = "Vendor")]
    public String Name { get; set; }
    [Display(Name = "Rec Chk #")]
    public string InCheckNumber { get; set; }
    [Display(Name = "Sent Chk #")]
    public string OutCheckNumber { get; set; }
    [Display(Name = "Invoice #")]
    public string InvoiceNumber { get; set; }
    [Display(Name = "PO #")]
    public string PurchaseOrderNumber { get; set; }
    [Display(Name = "Ledger Acct")]
    public string Title { get; set; }
    [Display(Name = "Credit")]
    public decimal? DebitAmount { get; set; }
    [Display(Name = "Debit")]
    public decimal? CreditAmount { get; set; }
    [Display(Name = "Transaction")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = false)]
    public DateTime TransactionDate { get; set; }
    [Display(Name = "Doc Link")]
    public string SavedDocument { get; set; }
    [Display(Name = "Created")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = false)]
    public DateTime CreatedDate { get; set; }
    [Display(Name = "Created By")]
    public string CreatedBy { get; set; }
    [Display(Name = "Type")]
    public string Type { get; set; }
    }
}

The in the Controller:

    private readonly AccountingEntities account = new AccountingEntities();
    // GET: Transaction
    public ActionResult Index()
    {
        return View(account.TransactionsView.ToList());
    }

In the View you just create a List View and put your @model at the top:

@model IEnumerable<YourProject.AccountingDTO.Entities.TransactionsView>

I tried to be as thorough as possible if I missed something I can answer any questions you may have. I use these all the time for List Views and tables

1 Comment

P.S. This was my first attempt at doing a SQLView with 2 databases. This would be done differently if the databases where on different servers. In my case they are on the same server..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.