Exception when using ASP.NET MVC and Entity Framework - c#

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.

Related

C# MVC Return ViewModel to List

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

LINQ Bind in List

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

How do I return related entities in web api, and call web api from separate mvc application

How can I return an entity with it's related entities in a Web API method, and call it from a MVC application.
I have a Web API in which I am returning a Person entity, I am also returning all the policies linked to the Person entity.
So a Person can have one or many Policies.
So far I am able to do this in my Web API controller.
The problem is calling my Web API in a separate MVC application.
Currently I can only return the Person record in my MVC application, I am struggling to return the Person and all related Policies in my MVC application.
In my MVC .cshtml view I am calling the ViewModel to pass the data to all the fields in the Web API.
This is my WebApi Method
Web Api ViewModel
Policies Class
MVC Controller calling Web Api method
This is the mvc cshtml view I am displaying the data from the web api in
[Route("{pklifeinsured}")]
public IHttpActionResult GetRec(int pklifeinsured)
{
var model = new Amendments_Interface_VM();
using (var db = new TestLiveEntities())
{
var ctx = db.LifeInsureds.Where(l => l.pkLifeInsured == pklifeinsured).FirstOrDefault();
if (ctx != null)
{
model = new Amendments_Interface_VM
{
pkLifeInsured = ctx.pkLifeInsured,
IdNumber = ctx.IdNumber,
Surname = ctx.Surname,
FirstName = ctx.FirstName,
Initials = ctx.Initials,
fkGender = ctx.fkGender,
DateOfBirth = ctx.DateOfBirth,
fkTitle = ctx.fkTitle,
fkMaritalStatus = ctx.fkMaritalStatus,
fkSmokerStatus = ctx.fkSmokerStatus,
fkLanguage = ctx.fkLanguage,
fkCommunicationMethod = ctx.fkCommunicationMethod,
Mobile = ctx.Mobile,
HomeTel = ctx.HomeTel,
EmailHome = ctx.EmailHome,
WorkTel = ctx.WorkTel,
EmailWork = ctx.EmailWork,
Postal_AddressLine1 = ctx.Postal_AddressLine1,
Postal_AddressLine2 = ctx.Postal_AddressLine2,
Postal_AddressLine3 = ctx.Postal_AddressLine3,
Postal_AddressLine4 = ctx.Postal_AddressLine4,
Postal_AddressLine5 = ctx.Postal_AddressLine5,
Physical_AddressLine1 = ctx.Physical_AddressLine1,
Physical_AddressLine2 = ctx.Physical_AddressLine2,
Physical_AddressLine3 = ctx.Physical_AddressLine3,
Physical_AddressLine4 = ctx.Physical_AddressLine4,
Physical_AddressLine5 = ctx.Physical_AddressLine5
};
model.PolicyHolder = db.PolicyHolders.Where(x => x.fkLifeInsured == pklifeinsured).Select(p => new PolicyHolderVM
{
PolicyNumber = p.PolicyNumber,
DOC = p.DOC,
fkLifeInsured = p.fkLifeInsured,
PolicyStatus = p.PolicyStatus,
RelationshipToLifeInsured = p.RelationshipToLifeInsured,
Package = p.Package,
Name = p.Name,
ContactNumber = p.ContactNumber,
ID_Reg_Num = p.ID_Reg_Num,
EmailAddress = p.EmailAddress
}).ToList();
}
}
return Ok(model);
}
public class Amendments_Interface_VM
{
public int pkLifeInsured { get; set; }
public string FirstName { get; set; }
public string Initials { get; set; }
public string Surname { get; set; }
public string fkTitle { get; set; }
public string fkGender { get; set; }
public string IdNumber { get; set; }
public Nullable<System.DateTime> DateOfBirth { get; set; }
public string fkMaritalStatus { get; set; }
public string fkSmokerStatus { get; set; }
public string fkLanguage { get; set; }
public string fkCommunicationMethod { get; set; }
public string WorkTel { get; set; }
public string Mobile { get; set; }
public string EmailWork { get; set; }
public string HomeTel { get; set; }
public string EmailHome { get; set; }
public string Postal_AddressLine1 { get; set; }
public Nullable<int> PA1_Id { get; set; }
public string Postal_AddressLine2 { get; set; }
public Nullable<int> PA2_Id { get; set; }
public string Postal_AddressLine3 { get; set; }
public Nullable<int> PA3_Id { get; set; }
public string Postal_AddressLine4 { get; set; }
public Nullable<int> PA4_Id { get; set; }
public string Postal_AddressLine5 { get; set; }
public Nullable<int> PA5_Id { get; set; }
public string Physical_AddressLine1 { get; set; }
public Nullable<int> PhyA1_Id { get; set; }
public string Physical_AddressLine2 { get; set; }
public Nullable<int> PhyA2_Id { get; set; }
public string Physical_AddressLine3 { get; set; }
public Nullable<int> PhyA3_Id { get; set; }
public string Physical_AddressLine4 { get; set; }
public Nullable<int> PhyA4_Id { get; set; }
public string Physical_AddressLine5 { get; set; }
public Nullable<int> PhyA5_Id { get; set; }
public IList<PolicyHolderVM> PolicyHolder { get; set; }
}
public class PolicyHolderVM
{
public int PolicyNumber { get; set; }
public Nullable<System.DateTime> DOC { get; set; }
public int fkLifeInsured { get; set; }
public string PolicyStatus { get; set; }
public string RelationshipToLifeInsured { get; set; }
public string Package { get; set; }
public string Name { get; set; }
public string ContactNumber { get; set; }
public string ID_Reg_Num { get; set; }
public string EmailAddress { get; set; }
}
public ActionResult Index(int? pklifeinsured)
{
var LifePolicy = new Amendments_Interface_VM();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(apiURL);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync($"{apiURL}/api/LifePol/{pklifeinsured}").Result;
if (response.IsSuccessStatusCode)
{
LifePolicy = response.Content.ReadAsAsync<Amendments_Interface_VM>().Result;
}
}
return View(LifePolicy);
}
#model WebApiTest_Invoke.Models.Amendments_Interface_VM
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div class="panel-group" id="MainScreen">
<div class="panel panel-default">
<div class="panel-heading">
<a data-toggle="collapse" data-parent="#MainScreen" href="#collapse1"><strong>Policy Holder/s</strong></a>
</div>
</div>
<div id="collapse1" class="panel-collapse collapse in">
<div class="panel-body">
<table class="table table-bordered">
<tr>
<th>
#Html.DisplayNameFor(model => model.PolicyNumber)
</th>
<td>
#Html.DisplayFor(model => Model.PolicyNumber)
</td>
<th>
#Html.DisplayNameFor(model => model.DOC)
</th>
<td>
#Html.DisplayFor(model => Model.DOC)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.fkLifeInsured)
</th>
<td>
#Html.DisplayFor(model => Model.fkLifeInsured)
</td>
<th>
#Html.DisplayNameFor(model => model.PolicyStatus)
</th>
<td>
#Html.DisplayFor(model => Model.PolicyStatus)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.RelationshipToLifeInsured)
</th>
<td>
#Html.DisplayFor(model => Model.RelationshipToLifeInsured)
</td>
<th>
#Html.DisplayNameFor(model => model.Package)
</th>
<td>
#Html.DisplayFor(model => Model.Package)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<td>
#Html.DisplayFor(model => Model.Name)
</td>
<th>
#Html.DisplayNameFor(model => model.ContactNumber)
</th>
<td>
#Html.DisplayFor(model => Model.ContactNumber)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.ID_Reg_Num)
</th>
<td>
#Html.DisplayFor(model => Model.ID_Reg_Num)
</td>
<th>
#Html.DisplayNameFor(model => model.EmailAddress)
</th>
<td>
#Html.DisplayFor(model => Model.EmailAddress)
</td>
</tr>
<tr>
</tr>
</table>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<a data-toggle="collapse" data-parent="#MainScreen" href="#collapse2"><strong>Life Insured</strong></a>
<h3 class="panel-title">
#using (Html.BeginForm("Index", "LifePol", FormMethod.Get))
{
<p style="padding-left:700px;">
Policy Number: #Html.TextBox("pklifeinsured")
<input type="submit" value="Search" />
</p>
}
</h3>
</div>
</div>
<div id="collapse2" class="panel-collapse collapse in">
<div class="panel-body">
<table class="table table-bordered">
<tr>
<th>
#Html.DisplayNameFor(model => model.Surname)
</th>
<td>
#Html.DisplayFor(model => Model.Surname)
</td>
<th>
#Html.DisplayNameFor(model => model.fkGender)
</th>
<td>
#Html.DisplayFor(model => Model.fkGender)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<td>
#Html.DisplayFor(model => Model.FirstName)
</td>
<th>
#Html.DisplayNameFor(model => model.fkSmokerStatus)
</th>
<td>
#Html.DisplayFor(model => Model.fkSmokerStatus)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.fkTitle)
</th>
<td>
#Html.DisplayFor(model => Model.fkTitle)
</td>
<th>
#Html.DisplayNameFor(model => model.DateOfBirth)
</th>
<td>
#Html.DisplayFor(model => Model.DateOfBirth)
</td>
</tr>
<tr>
<th>
#Html.DisplayNameFor(model => model.IdNumber)
</th>
<td>
#Html.DisplayFor(model => Model.IdNumber)
</td>
<th>
#Html.DisplayNameFor(model => model.Mobile)
</th>
<td>
#Html.DisplayFor(model => Model.Mobile)
</td>
</tr>
<tr>
</tr>
</table>
</div>
</div>
</div>
public Amendments_Interface_VM HttpClientCall(Amendments_Interface_VM value, string uri, int? pklifeinsured)
{
var client = new HttpClient { BaseAddress = new Uri(apiURL) };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var httpresult = client.GetAsync(apiURL).Result;
if(httpresult.IsSuccessStatusCode)
{
var result = httpresult.Content.ReadAsStringAsync().Result;
var data = JsonConvert.DeserializeObject<Amendments_Interface_VM>(result);
return data;
}
return new Amendments_Interface_VM();
}
error
I think you can create a model as below in your mvc application and then call the api
public class YourModel
{
public Person Person{get;set;}
public List<Policy> Policies {get;set;}
}
and then make webapi method to send data in the same format as that of model, or you can even use thissame model in webapi for sending data.
now in your webapi controller:
YourModel data=new YourModel();
Person person=new Person();
person.name="test name";
.
.
data.Person=person;
Policy policy1=new Policy();
policy1.name="test name";
.
.
Policy policy2=new Policy();
policy2.name="test name 2";
.
.
data.Policies.Add(policy1);
data.Policies.Add(policy2);
return Ok(data);
hope it helps :)
You can have the Policies property in you Person model and have it populated with necessary operation. Your model should look something like this. You can return all related entities by having entity property in the model.
public class Person
{
/* public int Id { get; set; }
* Other properties
*/
public List<PolicyHolderVM> policiesLst { get; set; }
}
I have created function to call the API. This will return the Person object coming from the API.
public Person HttpClientCall(Person value, string uri)
{
var client = new HttpClient { BaseAddress = new Uri(_baseUrl) };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var httpresult = client.GetAsync(uri).Result;
if (httpresult.IsSuccessStatusCode)
{
var result = httpresult.Content.ReadAsStringAsync().Result;
var data = JsonConvert.DeserializeObject<Person>(result);
return data
}
return new Person();
}

Referencing 1 column from 1 model to another

I have a requirement to show 1 column from different model on MVC. Im a first timer in mvc so im not really familiar with lambda convention...
So far I have this classes
article.cs
public class Article
{
[Key]
public int bl_id { get; set; }
[Column("bl_title")]
public string Title { get; set; }
[Column("bl_img")]
public string Image { get; set; }
[Column("bl_summ")]
public string Summary { get; set; }
[AllowHtml]
[Column("bl_content")]
public string Content { get; set; }
[Column("bl_author")]
public string Author { get; set; }
[DisplayFormat(ApplyFormatInEditMode =true, DataFormatString ="{0:MM/dd/yyyy}")]
[Column("bl_dtecrt")]
public DateTime DateCreated { get; set; }
}
the next class is the comments:
comments.cs
public class Comments
{
[Key]
public int ic_id { get; set; }
public int ic_blid { get; set; }
public string ic_comment { get; set; }
public DateTime ic_crtdte { get; set; }
public string ic_pcname { get; set; }
}
What I need is to have relate the Title Column from the Articles.cs models to the set of Comments... if it were on sql i could do a select query in this manner: select article.title, comments.ic_comment from articles, comments where articles.bl_id = comments.ic_blid
So far, the solution i tried is create a join in the controller then throw it to the view...
articlescontroller.cs
public ActionResult Comments()
{
var comm = from c in db.Comments
join a in db.Articles
on c.ic_blid equals a.bl_id
select c;
return View("Comments", comm.ToList());
}
EDIT: View
Comments.cshtml
#model IEnumerable<WebApplication3.Models.Comments>
#{
ViewBag.Title = "Comments";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.DisplayNameFor(model => model.ic_comment)
</th>
<th>
#Html.DisplayNameFor(model => model.ic_crtdte)
</th>
<th>
#Html.DisplayNameFor(model => model.ic_pcname)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
#Html.DisplayFor(ModelItem => item.Article.Title)
<tr>
<td>
#Html.DisplayFor(modelItem => item.ic_comment)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_crtdte)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_pcname)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ic_id }) |
#Html.ActionLink("Details", "Details", new { id=item.ic_id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ic_id })
</td>
</tr>
}
</table>
but my view is not catering the columns from the articles.
So my question is, how can I incorporate 1 or more columns from my Articles Model to my Comments Models then show them in the view? The reason behind this module is to maintain the comments done in the articles posted.
I tried putting this in the comments model:
public virtual Article Article { get; set; }
but i dont know how to use.
I hope you can help me...
You will first have to correct your Article class.
Since a Article can have many comments you need a property describing the same
(Please note the code is not tested)
public class Article{
...
public List<Comment> Comments {get; set;}
...
}
Now the place where you are trying to retrieve the data, include comments as well. Something like this:
public ActionResult Comments()
{
var comm = db.Article.Include(x=>x.Comments).ToList();
// This will get All article and include comments if any for each article.
return View("Comments", comm.ToList());
}
In your view you would have to iterate Comment for individual Article
#{
ViewBag.Title = "Comments";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#foreach (var item in Model) {
#Html.DisplayFor(ModelItem => item.Article.Title)
<tr>
<td>
#Html.DisplayFor(modelItem => item.Comments.ic_comment)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments.ic_crtdte)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments.ic_pcname)
</td>
<td
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ic_id }) |
#Html.ActionLink("Details", "Details", new { id=item.ic_id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ic_id })
</td>
</tr>
}
This can be done in below 2 ways. Create a Class which contains Comments and Title. Construct the object from this select result and pass it to Model.
Or have a Navigation property for comments in Article class. And modify LINQ-SQL as below.
Artice class
public class Article
{
[Key]
public int bl_id { get; set; }
[Column("bl_title")]
public string Title { get; set; }
[Column("bl_img")]
public string Image { get; set; }
[Column("bl_summ")]
public string Summary { get; set; }
[AllowHtml]
[Column("bl_content")]
public string Content { get; set; }
[Column("bl_author")]
public string Author { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
[Column("bl_dtecrt")]
public DateTime DateCreated { get; set; }
public virtual ICollection<Comments> Comments { get; set; }
}
Query
var comments1 = from c in comments
join a in articles
on c.ic_blid equals a.bl_id
select a;
View as below
#model IEnumerable<WebApplication1.Models.Article>
#{
ViewBag.Title = "Comments";
}
<h2>Comments</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>Title</th>
<th>ic_comment</th>
<th>ic_blid</th>
<th>ic_crtdte</th>
<th>ic_pcname</th>
</tr>
#foreach (var item1 in Model)
{
foreach (var item in item1.Comments)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item1.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_comment)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_blid)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_crtdte)
</td>
<td>
#Html.DisplayFor(modelItem => item.ic_pcname)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ic_id }) |
#Html.ActionLink("Details", "Details", new { id=item.ic_id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ic_id })
</td>
</tr>
}
}
</table>
Need to declare the Model for the View as dynamic. Please see
https://www.aspsnippets.com/Articles/Display-data-in-Single-View-from-Multiple-Tables-in-ASPNet-MVC.aspx
if it helps.
Also modify as below
var comm = from c in db.Comments
join a in db.Articles
on c.ic_blid equals a.bl_id
select new {c,a.title};
The answer of #Jja is the accepted answer but since i had a trouble with navigation property...
As per this stackoverflow link: The Name value should be a valid navigation property name.
My problem when using ForeignKey, the virtual table you're connecting to must have the same name on the [ForeignKey("")] tag. Before, my Comments class was defined as this:
[Table("Intranet_Comments")]
public class Intranet_Comments
{
[Key]
public int ic_id { get; set; }
[ForeignKey("Intranet_Article")]
public int ic_blid { get; set; }
public string ic_comment { get; set; }
public DateTime ic_crtdte { get; set; }
public string ic_pcname { get; set; }
public virtual Article Article { get; set; }
}
And it throws navigation error... i re-wrote this class into:
[Table("Intranet_Comments")]
public class Intranet_Comments
{
[Key]
public int ic_id { get; set; }
[ForeignKey("Article")]
public int ic_blid { get; set; }
public string ic_comment { get; set; }
public DateTime ic_crtdte { get; set; }
public string ic_pcname { get; set; }
public virtual Article Article { get; set; }
}
The foreign key property name must be the same name as the virtual property set..
i hope this helps!

.NET Use A Related Table To Decide What Information to Show

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.

Categories

Resources