Reputation: 237
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>
Upvotes: 0
Views: 1618
Reputation: 237
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
Upvotes: 0
Reputation: 9131
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)
Upvotes: 1
Reputation: 111
Public class AcctModel
{
public IEnumerable<AccountingViewModels> Items {get; set;}
}
In view.cshtml
foreach(var item in Model.Items)
{
// Your code here
}
Upvotes: 0