I have a client model a identifier model and a link model. The identifier model contains websites available for posting, client model contains clients that need a specific amount of links per month. A link object in the link model contains the Identifier ID and the Client ID. I want another view displaying a table of all the Identifier ID's that haven't been used with a Client ID's in the Link model table if this makes sense?
Client Model:
namespace Linkofy.Models
{
public class Client
{
public int ID { get; set; }
[Required]
[Display(Name = "Client")]
public string clientN { get; set; }
[Url]
[Display(Name = "Website")]
public string homePage{ get; set; }
[EmailAddress]
[Display(Name = "Contact Email")]
public string clientEmail { get; set; }
[Display(Name = "Contact Name")]
public string contName { get; set; }
[Display(Name = "Monthly")]
public int monthlyQuota { get; set; }
[Display(Name = "TF")]
public int TrustFlow { get; set; }
[Display(Name = "CF")]
public int CitationFlow { get; set; }
public int RI { get; set; }
public int? MJTopicsID { get; set; }
public virtual MJTopics MJTopics { get; set; }
public int UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
public virtual ICollection<Link> Links { get; set; }
public virtual ICollection<Status> Statuss { get; set; }
}
}
Link Model:
namespace Linkofy.Models
{
public class Link
{
public int LinkID { get; set; }
[Required]
[Display(Name = "Linking Page")]
public string Obdomain { get; set; }
public int? ClientID { get; set; }
public virtual Client Client { get; set; }
[Required]
[Display(Name = "Outbound Link")]
public string Obpage { get; set; }
[Required]
[Display(Name = "Anchor Text")]
public string Anchor { get; set; }
[Required]
[Display(Name = "Date Built")]
public DateTime BuildDate { get; set; }
public int IdentifierID { get; set; }
public virtual Identifier Identifier { get; set; }
public int? UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
}
}
Domain Model:
public class Identifier
{
public enum Ltype
{
GuestPost, ExistingLink
}
public int ID { get; set; }
[Url]
[Required]
[Display(Name = "Domain")]
public string domain { get; set; }
[Required]
[Display(Name = "Contact Email")]
[EmailAddress]
public string contact { get; set; }
[Display(Name = "Contact Name")]
public string contactname { get; set; }
[Required]
[Display(Name = "Price")]
public int price { get; set; }
[Display(Name = "Type of Link")]
public Ltype? type { get; set; }
[Display(Name = "TF")]
public int TrustFlow { get; set; }
[Display(Name = "CF")]
public int CitationFlow { get; set; }
public int RI { get; set; }
public int? MJTopicsID { get; set; }
public virtual MJTopics MJTopics { get; set; }
public virtual UserTable UserTable { get; set; }
public int UserTableID { get; set; }
public virtual ICollection<Link> Links { get; set; }
}
}
Model View:
#model IEnumerable<Linkofy.Models.Identifier>
#{
ViewBag.Title = "Index";
}
#section Styles {
<link href="#Url.Content("~/Styles/Index.css")" rel="stylesheet" type="text/css" />
}
<h1>Domain List</h1>
<p class="options"> #Html.ActionLink("Add New", "Create") | #Html.ActionLink("Add Bulk", "CreateBulk") </p>
<div class="row">
<div class="col-md-12">
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.domain)
</th>
<th>
#Html.DisplayNameFor(model => model.contact)
</th>
<th>
#Html.DisplayNameFor(model => model.contactname)
</th>
<th>
#Html.DisplayNameFor(model => model.price)
</th>
<th>
#Html.DisplayNameFor(model => model.type)
</th>
<th>
#Html.DisplayNameFor(model => model.TrustFlow)
</th>
<th>
#Html.DisplayNameFor(model => model.CitationFlow)
</th>
<th>
#Html.DisplayNameFor(model => model.RI)
</th>
<th>
#Html.DisplayNameFor(model => model.MJTopics.topicalTF)
</th>
<th></th>
</tr>
#foreach (var item in Model.Where(Model.Links.Item => item.ClientID != ViewBag.ClientID)) {
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.domain)
</td>
<td>
#Html.DisplayFor(modelItem => item.contact)
</td>
<td>
#Html.DisplayFor(modelItem => item.contactname)
</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
<td>
#Html.DisplayFor(modelItem => item.type)
</td>
<td>
#Html.DisplayFor(modelItem => item.TrustFlow)
</td>
<td>
#Html.DisplayFor(modelItem => item.CitationFlow)
</td>
<td>
#Html.DisplayFor(modelItem => item.RI)
</td>
<td>
#Html.DisplayFor(modelItem => item.MJTopics.topicalTF)
</td>
<td>
#Html.ActionLink(" ", "Details", new { id=item.ID }, new {#class= "glyphicon glyphicon-home" })
#Html.ActionLink(" ", "Edit", new { id=item.ID }, new {#class= "glyphicon glyphicon-edit" })
#Html.ActionLink(" ", "Delete", new { id=item.ID }, new {#class= "glyphicon glyphicon-trash" })
</td>
</tr>
}
</table>
</div>
</div>
I achieved this using LINQ statements as mentioned by Zorkind in comments.
Related
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">
Create Full
</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>
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)
Public class AcctModel
{
public IEnumerable<AccountingViewModels> Items {get; set;}
}
In view.cshtml
foreach(var item in Model.Items)
{
// Your code here
}
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
I'm getting a null reference exception when I add the following to the Client Details view:
<dt>
#Html.DisplayNameFor(model => model.Contacts)
</dt>
<dd>
<table class="table">
<tr>
<th>FN</th>
<th>LN</th>
<th>Email</th>
<th>Contact Type</th>
</tr>
#foreach (var item in Model.Contacts)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FN)
</td>
<td>
#Html.DisplayFor(modelItem => item.LN)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContactType)
</td>
</tr>
}
</table>
</dd>
Why am I getting a null reference exception at #Html.DisplayNameFor(model => model.Contacts) and how can I fix it?
The following is the Client class with the data annotations removed to make it easier to read:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace scms_core.Models
{
public class Client
{
public int Id { get; set; }
public string CrtdBy { get; set; }
public DateTime CrtdDt { get; set; }
public string FN { get; set; }
public string LN { get; set; }
public string BN { get; set; }
public int ClientTypeId { get; set; }
public tlClientType ClientType { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
}
The following is the Contact class, also with the data annotations removed to make it easier to read:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace scms_core.Models
{
public class Contact
{
public int Id { get; set; }
public string CrtdBy { get; set; }
public DateTime CrtdDt { get; set; }
public string FN { get; set; }
public string LN { get; set; }
public string Email { get; set; }
public int ContactTypeId { get; set; }
public tlContactType ContactType { get; set; }
public int ClientId { get; set; }
public virtual Client Client { get; set; }
}
}
When I remove the reference the code that is supposed to get the Contact information, the details page works. It just fails when I add this code to the view. Below is the Client Details View:
#model scms_core.Models.Client
#{
ViewData["Title"] = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Details</h1>
<div>
<h4>Client</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.CrtdBy)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.CrtdBy)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.CrtdDt)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.CrtdDt)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.FN)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.FN)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.LN)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.LN)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.BN)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.BN)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.ClientType)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.ClientType.ClientType)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Contacts)
</dt>
<dd>
<table class="table">
<tr>
<th>FN</th>
<th>LN</th>
<th>Email</th>
<th>Contact Type</th>
</tr>
#foreach (var item in Model.Contacts)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FN)
</td>
<td>
#Html.DisplayFor(modelItem => item.LN)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContactType)
</td>
</tr>
}
</table>
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="#Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>
Below is the controller code:
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var client = await _context.Clients
.Include(c => c.ClientType)
.FirstOrDefaultAsync(m => m.Id == id);
if (client == null)
{
return NotFound();
}
return View(client);
}
you should initialize Contacts collection in the Client model constructor like this
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace scms_core.Models
{
public class Client
{
public Client()
{
Contacts = new HashSet<Contact>();
}
public int Id { get; set; }
public string CrtdBy { get; set; }
public DateTime CrtdDt { get; set; }
public string FN { get; set; }
public string LN { get; set; }
public string BN { get; set; }
public int ClientTypeId { get; set; }
public tlClientType ClientType { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
}
Should be like this, change Id to ClientID and make a [Key] and [Table] where you want to have primary key and making a table:
[Table("Client")]
public class Client
{
[Key]
public int ClientID { get; set; }
public string CrtdBy { get; set; }
public DateTime CrtdDt { get; set; }
public string FN { get; set; }
public string LN { get; set; }
public string BN { get; set; }
public int ClientTypeID { get; set; }
[ForeignKey("ClientTypeID")]
public ClientType ClientType { get; set; }
public int ContactID { get; set; }
[ForeignKey("ContactID")]
public virtual Contact Contact { get; set; }
public ICollection<Contact> Contacts { get; set; }
}
Change Id to ContactID
[Table("Contact")]
public class Contact
{
[Key]
public int ContactID { get; set; }
public string CrtdBy { get; set; }
public DateTime CrtdDt { get; set; }
public string FN { get; set; }
public string LN { get; set; }
public string Email { get; set; }
public int ContactTypeID { get; set; }
[ForeignKey("ContactTypeID")]
public virtual ContactType ContactType { get; set; }
public int ClientID { get; set; }
[ForeignKey("ClientID")]
public virtual Client Client { get; set; }
}
Your controller should declare a list and send the view model to razor page. Should look something like this:
public async Task<ActionResult> Contacts()
{
var allClients = await _context.Clients.ToList();
List<Contact> viewModel = allClients.Select(x => new Contacts
{
FN = x.FN,
LN = x.LN,
Email = x.Email,
ContactType = x.ContactType
}).ToList();
return View(viewModel);
}
You should do the same for all models that are going to create the database. In your Contacts page, you did not mention which #model you are using, but it should look something like this: #model List<YourProject.UI.Models.Contacts>
i want to bind in list, how to do that, please see my code below
this below is my Controller
var transaction = await (from a in _context.Transaction group a by a.Nobukti into pg
join b in _context.ChartAccount on pg.FirstOrDefault().Kodeakun
equals b.Kodeakun
select new Transaksi
{
Nobukti = pg.FirstOrDefault().Nobukti,
Tanggal = pg.FirstOrDefault().Tanggal,
Keterangan = pg.FirstOrDefault().Keterangan,
Trans = pg.ToList()
}).ToListAsync();
return View(transaction);
See my Trans = pg.ToList() in Controller, inside pg.ToList() there are Kodeakun, and i want bind to Kodeakun = a.Kodeakun + b.Kodeakun
This below is my Model
public class ChartAccount
{
[Key]
public string Kodeakun { get; set; }
public string Namaakun { get; set; }
[DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = true)]
public decimal Saldo { get; set; }
}
public class Transaksi
{ [Key]
public int Iud { get; set; }
public int Id { get; set; }
public string Nobukti { get; set; }
public string Kodeakun { get; set; }
public string Keterangan { get; set; }
[DataType(DataType.Date)]
public DateTime Tanggal { get; set; }
[DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = false)]
public decimal Debit { get; set; }
[DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = false)]
public decimal Kredit { get; set; }
public virtual List<Transaksi> Trans { get; set; }
}
this below is my view
<table class="table">
#foreach (var item in Model)
{
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Nobukti) :
#Html.DisplayFor(modelItem => item.Nobukti)
</th>
<th>
#Html.DisplayNameFor(model => model.Keterangan) :
#Html.DisplayFor(modelItem => item.Keterangan)
</th>
<th>
#Html.DisplayNameFor(model => model.Tanggal) :
#Html.DisplayFor(modelItem => item.Tanggal)
</th>
</tr>
</thead>
<tbody>
#foreach (var transaksi in item.Trans)
{
<tr>
<td>
#Html.DisplayFor(modelItem => transaksi.Kodeakun)
</td>
<td>
#if (transaksi.Debit == 0) { }
else
{
#Html.DisplayFor(modelItem => transaksi.Debit)
}
</td>
<td>
#if (transaksi.Kredit == 0) { }
else
{
#Html.DisplayFor(modelItem => transaksi.Kredit)
}
</td>
</tr>
}
</tbody>
}
</table>
sorry for my bad english, i use ASP Net Core 2.2
Very new to ASP.NET MVC and Entity Framework.
I'm trying to set up a database with three tables, when I run my code and go to the page "Tickets", I get the following exception:
There is already an open DataReader associated with this Command which must be closed first.
Class 1
public class Ticket
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
[ForeignKey("Practice")]
public int PracticeID { get; set; }
public string Contact { get; set; }
public string Category { get; set; }
//insert Support type using ViewBag (Support type listed in Models.Practices)
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime Due { get; set; }
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime TimeLogged { get; set; }
[ForeignKey("Consultant")]
public int ConsultantID { get; set; }
public string ConsultantName { get; set; }
public string Status { get; set; }
public virtual Practice Practice { get; set; }
public virtual Consultant Consultant { get; set; }
}
Class 2:
public class Practice
{
[Key]
public int PracticeID { get; set; }
[Display(Name = "Practice Name")]
public string PracName { get; set; }
[Display(Name = "Practice Number")]
public int PracNumber { get; set; }
public string Contact { get; set; }
[Display(Name = "Support Type")]
public string Support { get; set; }
public string Tel { get; set; }
public string Cell { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public string Address { get; set; }
public virtual List<Ticket> Ticket { get; set; }
}
Class 3:
public class Consultant
{
[Key]
public int ConsultantID { get; set; }
public string Name { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public string Role { get; set; }
public virtual List<Ticket> Ticket { get; set; }
}
I have a search function in my TicketsController:
public ActionResult Index(string searchString, string Consultants)
{
var UserLst = new List<string>();
var UserQry = from d in db.Consultants
orderby d.Name
select d.Name;
UserLst.AddRange(UserQry.Distinct());
ViewBag.User = new SelectList(UserLst);
var tickets = from m in db.Ticket
select m;
if (!String.IsNullOrEmpty(searchString))
{
tickets = tickets.Where(s => s.Description.Contains(searchString));
}
if (!string.IsNullOrEmpty(Consultants))
{
tickets = tickets.Where(x => x.ConsultantName == Consultants);
}
return View(tickets);
}
The error seems to be coming from the HTML code in the INDEX.
#model IEnumerable<MAD.Models.Ticket>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<p>
User: #Html.DropDownList("User", "All")
Description: #Html.TextBox("SearchString") <br />
<input type="submit" value="Search" />
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Consultant.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Practice.PracName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Contact)
</th>
<th>
#Html.DisplayNameFor(model => model.Category)
</th>
<th>
#Html.DisplayNameFor(model => model.Due)
</th>
<th>
#Html.DisplayNameFor(model => model.TimeLogged)
</th>
<th>
#Html.DisplayNameFor(model => model.Status)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Consultant.Name)--ERROR CODE
</td>
<td>
#Html.DisplayFor(modelItem => item.Practice.PracName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Contact)
</td>
<td>
#Html.DisplayFor(modelItem => item.Category)
</td>
<td>
#Html.DisplayFor(modelItem => item.Due)
</td>
<td>
#Html.DisplayFor(modelItem => item.TimeLogged)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
You have passed in an IQueryable from your controller as your model - called tickets in the controller method. When you start your for each loop on the model, EF starts retrieving results through the connection, but it doesn't actually finish using the connection for this until the end of the loop. The line which is causing the error is trying to access the related Consultant property, which triggers EF to try to load that from the DB, but that causes an exception because you are still in the loop and it is still using the connection to retrieve the tickets query.
The easiest way around this is to force EF to retrieve the results before the loop. I would go for changing the final line in the controller to View (tickets.ToArray) or similar.
I'm not sure, but enabling multiple active result sets might also fix this.
I have an MVC 4 application and what I am trying to do is to list the events of a specific booking (together with some information about the booking - this by using viewbags) in the same page (using the Events model only). So that goes fine until I add a dropdown-list to change the statusCode of that booking (that all the listing events are related to).
#Html.DropDownList("StatusCodeList")
Whatever I do, it doesn't change. Please help me to find out why !
Models
public class Booking
{
[Key]
public int BookingId { get; set; }
[DisplayName("Event Title")]
public string EventTitle { get; set; }
[DisplayName("Requester's Name")]
public string UserFullName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public System.DateTime RequestDate { get; set; }
[DisplayName("Event Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public System.DateTime EventDate { get; set; }
[DisplayName("Login")]
public string Login { get; set; }
[DisplayName("NetworkID")]
public string NetworkID { get; set; }
public string BookingTotalCost { get; set; }
[ForeignKey("StatusCode")]
public int StatusCodeId { get; set; }
public virtual StatusCode StatusCode { get; set; }
[Required(ErrorMessage = "Event Type is required.")]
[ForeignKey("CateringType")]
public int CateringTypeId { get; set; }
public virtual CateringType CateringType { get; set; }
public List<Event> Events { get; set; }
}
public class Event
{
[Key]
public int EventId { get; set; }
[Required(ErrorMessage = "Event Leader is required")]
[DisplayName("Event Leader")]
public string EventLeader { get; set; }
[Required(ErrorMessage = "Budget Code is required")]
[DisplayName("Budget Code")]
public string EventBudgetCode { get; set; }
[DisplayName("Special Requirements")]
public string SpecialRequirements { get; set; }
[DisplayName("Event Cost")]
public string EventTotalCost { get; set; }
[Required(ErrorMessage = "Participants are required")]
[Range(1, 300, ErrorMessage = "Participants must be </br> between 1 and 300")]
[StringLength(3, ErrorMessage = "Max 3 digits")]
[DisplayName("Participants")]
public string EventParticipants { get; set; }
[Required(ErrorMessage = "Room is required")]
[DisplayName("Room Number")]
[ForeignKey("Room")]
public int RoomId { get; set; }
public virtual Room Room { get; set; }
[Required(ErrorMessage = "Start Time is required")]
[DisplayName("Start Time")]
[DataType(DataType.Time)]
public DateTime EventStartDateTime { get; set; }
[Required(ErrorMessage = "End Time is required")]
[DisplayName("End Time")]
[DataType(DataType.Time)]
[DateEnd(DateStartProperty = "EventStartDateTime")]
public DateTime EventEndDateTime { get; set; }
[ForeignKey("Booking")]
public int BookingId { get; set; }
public virtual Booking Booking { get; set; }
[Required(ErrorMessage = "Dietary Requirements are required")]
[DisplayName("Dietary Requirement")]
[ForeignKey("DietaryRequirement")]
public int DietaryRequirementId { get; set; }
public virtual DietaryRequirement DietaryRequirement { get; set; }
public ICollection<CateringItem> CateringItems { get; set; }
}
Controller
public ActionResult RequestDetails(int id)
{
var eventList = from s in SystemDB.Events
where s.BookingId == id
select s;
Booking booking = SystemDB.Bookings.Find(id);
ViewBag.Date = booking.EventDate.ToShortDateString();
ViewBag.BookingId = id;
ViewBag.Requester = booking.UserFullName;
ViewBag.RequesterEmail = booking.NetworkID + "#gmail.com";
var sum = (from s in SystemDB.Events.ToList()
where s.BookingId == id
select Convert.ToDecimal(s.EventTotalCost)).Sum();
if (booking.BookingTotalCost == null && sum == 0)
{
ViewBag.BookingTotalCost = "0";
}
else
{
ViewBag.BookingTotalCost = sum;
}
TempData["BookingId"] = id;
var statuscodes = SystemDB.StatusCodes.Where(s => s.StatusCodeId != 1);
ViewBag.StatusCodeList = new SelectList(statuscodes, "StatusCodeId", "StatusCodeName", booking.StatusCodeId);
return View(eventList);
}
[HttpPost]
[ActionName("RequestDetails")]
public ActionResult PostRequestDetails(int id)
{
TempData["BookingId"] = id;
var eventList = from s in SystemDB.Events
where s.BookingId == id
select s;
ViewBag.BookingId = id;
Booking booking = SystemDB.Bookings.Find(id);
ViewBag.Date = booking.EventDate.ToShortDateString();
ViewBag.BookingId = id;
ViewBag.Requester = booking.UserFullName;
ViewBag.RequesterEmail = booking.NetworkID + "#gmail.com";
var sum = (from s in SystemDB.Events.ToList()
where s.BookingId == id
select Convert.ToDecimal(s.EventTotalCost)).Sum();
booking.BookingTotalCost = sum.ToString();
var statuscodes = SystemDB.StatusCodes.Where(s => s.StatusCodeId != 1);
ViewBag.StatusCodeList = new SelectList(statuscodes, "StatusCodeId", "StatusCodeName", booking.StatusCodeId);
if (ModelState.IsValid)
{
SystemDB.Entry(booking).State = EntityState.Modified;
SystemDB.SaveChanges();
return RedirectToAction("RequestList", "Admin", new { id = id });
}
return View(eventList);
}
View
#model IEnumerable<CateringBookingSystem.Models.Event>
#using (Html.BeginForm())
{
<span><b>Booking for: </b>#ViewBag.Date</span> <span style="padding-left:20px;"><b>Total Cost: </b>£#ViewBag.BookingTotalCost</span> <span style="padding-left:20px;"><b>Requester: </b>#ViewBag.Requester</span> <span style="padding-left:20px;"><b>Status: </b> #Html.DropDownList("StatusCodeList") </span>
<table id="listTable" style="width:100%" >
<tr style="color:white;">
<th>
#Html.DisplayNameFor(model => model.EventLeader)
</th>
<th>
#Html.DisplayNameFor(model => model.EventStartDateTime)
</th>
<th>
#Html.DisplayNameFor(model => model.EventEndDateTime)
</th>
<th>
#Html.DisplayNameFor(model => model.Room.RoomNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.EventParticipants)
</th>
<th>
#Html.DisplayNameFor(model => model.EventTotalCost)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.EventLeader)
</td>
<td>
#Html.DisplayFor(modelItem => item.EventStartDateTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.EventEndDateTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.Room.RoomNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.EventParticipants)
</td>
<td>
£#Html.DisplayFor(modelItem => item.EventTotalCost)
</td>
<td>
#Html.ActionLink("Amend", "EditEventForEventList", new { EventId = item.EventId, Amend = "True" }) |
<a class="clicker" dialogid="#item.EventId" href="#"> View Catering</a> |
<div class="dialog #item.EventId " title="">
<p>#{Html.RenderAction("ViewEvent", "Home", new { EventId = item.EventId });}</p>
</div>
#Html.ActionLink("Delete", "DeleteEventFromEventList", new { id = item.EventId })
</td>
</tr>
}
</table>
<div style="padding-top:50px;">
<input type="submit" value="submit" />
</div>
}