Data of Multiple related tables not shown in Razor page - c#

I am using .net core 2.2. When I run the following output is shown in the list of FacultyInterestItem with the Faculty or Keywords table data missing. Although the Faculties and Keywords classes are connected with the FacltyInterestItems
The following is the razor page
<tbody>
#foreach (var item in Model.FacultyInterestItems)
{
<tr>
<td> #Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Faculty.FacultyId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Keyword.Name)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.Id">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
The cs file of the Razor page having OnGetAsync() method where it connects and take data from WebAPI.
public async Task OnGetAsync()
{
List<FacultyInterestItems> facultyInterestItem = new List<FacultyInterestItems>();
HttpClient client = _api.Initial();
HttpResponseMessage res = await client.GetAsync("api/FacultyInterestItems");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
facultyInterestItem = JsonConvert.DeserializeObject<List<FacultyInterestItems>>(result);
}
List<Faculties> listOfFaculty = new List<Faculties>();
res = await client.GetAsync("api/Faculties");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
listOfFaculty = JsonConvert.DeserializeObject<List<Faculties>>(result);
}
List<Keywords> listOfKeywords = new List<Keywords>();
res = await client.GetAsync("api/Keywords");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
listOfKeywords = JsonConvert.DeserializeObject<List<Keywords>>(result);
}
FacultyInterestItems = facultyInterestItem;
Keywords = listOfKeywords;
Faculties = listOfFaculty;
}
The procedure OnGetAscyn() in razor page cs file, gets data from API. Here is the get method in the controller of API that connects to the DB and fetch data.
[HttpGet]
public async Task<ActionResult<IEnumerable<FacultyInterestItems>>> GetFacultyInterestItems()
{
return await _context.FacultyInterestItems.ToListAsync();
}
Here is the model:
The Faculties Table
public partial class Faculties
{
public Faculties()
{
FacultyInterestItems = new HashSet<FacultyInterestItems>();
SuggestedKeywords = new HashSet<SuggestedKeywords>();
}
public long Id { get; set; }
public string FacultyId { get; set; }
public DateTime? UpdateDate { get; set; }
public DateTime? InsertDate { get; set; }
public virtual ICollection<FacultyInterestItems> FacultyInterestItems { get; set; }
public virtual ICollection<SuggestedKeywords> SuggestedKeywords { get; set; }
}
The FacultyInterestItems tables:
public partial class FacultyInterestItems
{
public long Id { get; set; }
public long? FacultyId { get; set; }
public int? KeywordId { get; set; }
public DateTime InsertDate { get; set; }
public DateTime UpdateDate { get; set; }
public virtual Faculties Faculty { get; set; }
public virtual Keywords Keyword { get; set; }
}
the Keywords table:
public partial class Keywords
{
public Keywords()
{
FacultyInterestItems = new HashSet<FacultyInterestItems>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime InsertDate { get; set; }
public DateTime UpdateDate { get; set; }
public int? DepartmentId { get; set; }
public virtual Departments Department { get; set; }
public virtual ICollection<FacultyInterestItems> FacultyInterestItems { get; set; }
}
Data of Faculty and Keyword is not fetched from the DB. Please let me know the solution

Try to call Include method
_context.FacultyInterestItems.Include(x => x.Faculty).Include(x => x.Keyword).ToListAsync()

Related

How to display value by selecting from model in the controller ASP MVC

I want to display a name in the razor page by select it from a model and pass it through Viewbag in the controller.
Controller
public IActionResult sheet()
{
var tp1 = _db.Topic.Where(t => t.sheet_id == 1).ToList();
var tp1name = tp1.Select(t => t.topic1name);
ViewBag.tp1name = tp1name;
return View();
}
Model
public class Topic
{
[Key]
public int topic_id { get; set; }
[Required]
public int sheet_id { get; set; }
[Required]
public string topic1name { get; set; }
[Required]
public string topic2name { get; set; }
}
public class Transaction
{
[Key]
public int id { get; set; }
[Required]
public int sheet_id { get; set; }
[Required]
public string topic1score { get; set; }
}
View page
#model transaction
<table class="table">
<tr>
<td rowspan="2">1</td>
<td rowspan="2">#ViewBag.tp1name</td>
<td rowspan="2">30</td>
<td>Below average</td>
<td>Average</td>
<td>Above average</td>
</tr>
It returns
System.Linq.Enumerable+SelectListIterator`2[UserLoginApp.Models.Topic,System.String] in the view page instead of topic1name
tp1 is a list of topics.
so when you do a select it creates a new Enumerable en for each item in tp1 it selects the value of topic1name.
Thus creating an Enumerable+SelectListIterator
I think you want the value of one item:
var tp1 = _db.Topic.FirstOrDefault(t => t.sheet_id == 1)
if(tp1 != null)
ViewBag.tp1name = tp1.topic1name;

How do you reference a foreign key from a razor view page?

New to .net core here and I am going through razor tutorials and trying to add my own things to it. I have two tables: Order and Stock. I can list all Orders or all stocks, but when I want to list all Orders, I want to display the stock name (not the stockID) in the view page (near end of code). How do you reference the foreign key 'stockID' from the view page? Here is my code:
public class OrderModel
{
public int Id { get; set; }
public string OrderName { get; set; }
public DateTime OrderDate { get; set; } = DateTime.UtcNow;
public int Quantity { get; set; }
public decimal StockUnitCost { get; set; }
public decimal StockTotalCost { get; set; }
public decimal WinLoseAmt { get; set; }
public int StockId { get; set; }
}
public class StockModel
{
public int Id { get; set; }
public string StockName { get; set; }
public string StockTicker { get; set; }
public string StockType { get; set; }
public string Sector { get; set; }
}
public class OrderDisplayModel : PageModel
{
private readonly IOrderData _orderData;
private readonly IStockData _stockData;
public OrderModel Order { get; set; }
public List<OrderModel> orderList { get; set; }
public OrderDisplayModel(IOrderData orderData, IStockData stockData)
{
_orderData = orderData;
_stockData = stockData;
}
public async Task OnGet()
{
orderList = await _orderData.GetOrder();
}
}
<h1>My Orders</h1>
<table class="'table table-striped">
<thead class="thead-dark">
<tr>
<th>Order Name</th>
<th>Stock</th>
<th>Quantity</th>
<th>Cost Basis</th>
<th>Total Cost</th>
<th>Open Mkt Gain</th>
<th>Order Date</th>
</tr>
</thead>
<tbody>
#foreach (var order in Model.orderList)
{
<tr>
<td>#order.OrderName</td>
<td>#Model.StockPurchased</td>
<td>#order.StockId</td>
<td>#order.Quantity</td>
<td>#order.StockUnitCost</td>
<td>#order.StockTotalCost</td>
<td>#order.WinLoseAmt</td>
<td>#order.OrderDate</td>
</tr>
}
</tbody>
</table>
Thanks!
Create a virtual property and make it ForeignKey (and InverseProperty if you want to have another virtual collection property from Stock to Orders).
Something like this
....
public int StockId { get; set; }
[ForeignKey(nameof(StockId))]
[InverseProperty("Orders")]
public virtual Stock Stock { get; set; }
Then, you can either .Include(s=>s.Stock) in you context call and access it like order.Stock.StockName. Or setup Lazy loading (which requires a a bit more work in recent .NET core versions) and you access it without needing to Inclue it.

C# ASP.ΝΕΤ MVC many to many find by id, result count = 0, why?

I'm doing a project for exercises. I need to write a query that will return me a list of tours for the client. Unfortunately, my query returns 0. I searched all the stackoverflows but found nothing. I've been sitting on it for 2 days :-(
This is my class:
public class Wycieczka
{
public Wycieczka()
{
this.Klienci = new HashSet<Klient>();
}
[Key]
public int IdWycieczka { get; set; }
[Required(ErrorMessage = "Pole wymagane")]
[MaxLength(50, ErrorMessage = "Dlugosc nazwy to maksymalnie 50 znakow")]
public string nazwa { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> dataWyjazdu { get; set; }
[Required]
public int iloscOsob { get; set; }
public virtual Kierowca Kierowca { get; set; }
public virtual ICollection<Klient> Klienci { get; set; }
}
public class Klient
{
public Klient()
{
this.Wycieczki = new HashSet<Wycieczka>();
}
[Key]
public String pesel { get; set; }
[Required(ErrorMessage = "Pole wymagane")]
[MaxLength(50, ErrorMessage = "Dlugosc nazwy to maksymalnie 50 znakow")]
public string Imie { get; set; }
[Required]
[MaxLength(50)]
public string Nazwisko { get; set; }
[Required]
public string adres_email { get; set; }
public virtual ICollection<Wycieczka> Wycieczki { get; set; }
}
and my method in controller:
public ViewResult Wycieczki(String pesel)
{
var wycieczka = (_context.Klient
.Where(c => c.pesel == pesel)
.Select(c => c.Wycieczki)).ToList();
return View(wycieczka);
}
my View:
#model IEnumerable<ApbdProjekt2.Models.Wycieczka>
#{
ViewBag.Title = "Lista Wycieczek dla klienta";
}
<div class="container">
<h2>Lista Wycieczek dla klienta</h2>
<table class="table">
<tr>
<th>Nazwa</th>
<th>Data Wyjazdu</th>
<th>ilosc osob</th>
</tr>
#foreach (var w in Model)
{
<tr>
<td>#w.nazwa</td>
<td>#w.dataWyjazdu</td>
<td>#w.iloscOsob</td>
</tr>
}
</table>
</div>
Please some advice :-)
EDIT:
thank you for help :) i solved my problem. The problem was on my side. In another view, where i get this view i have wrong name of pesel. I have id == pesel. Thank you :-)
Probably the problem is no database.
Make some examples with created lists created for the database.
Test:
public ViewResult Wycieczki(String pesel)
{
var _ListKient = new List<Klient> { new Klient { pesel = "AA" }, new Klient { pesel = "BB" }, new Klient { pesel = "CC" }, new Klient { pesel = "DD" } };
var wycieczka = (_ListKient.Klient).Where(c => c.pesel == pesel).Select(c => c.Wycieczki)).ToList();
return View(wycieczka);
}
Just an example to see if it is returned.
I hope I have helped you

Cannot implicitly convert type 'System.Collections.Generic.List to 'System.Collections.Generic.IEnumerable error in asp.net mvc

I got the error from my below code
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.List to 'System.Collections.Generic.IEnumerable<Theme_Hisaab.Models.CustomerLedger>'. An explicit conversion exists (are you missing a cast?)
Controller Code
public class CustomerLedgerController : Controller
{
// GET: CustomerLedger
Hisaab_ApplicationEntities7 db = new Hisaab_ApplicationEntities7();
IEnumerable<CustomerLedger> CustomerLedger = null;
public ActionResult Index()
{
CustomerLedger = (from cus_data in db.Customer_Data
join so in db.SalesOrder on cus_data.Customer_ID equals so.SalesOrder_ID
join sd in db.SalesOrderDetail on so.SalesOrder_ID equals sd.SalesOrderDetail_ID
select new
{
cus_data.Customer_Name,
cus_data.Customer_ID,
so.SalesOrder_ID,
so.FK_Customer_ID,
sd.SalesOrderDetail_ID,
sd.SalesOrder_Unit_Price,
sd.SalesOrder_Total,
sd.FK_SalesOrder_ID,
sd.FK_Product_ID
}
).ToList();
return View(CustomerLedger);
}
}
ViewModel
public class CustomerLedger
{
public int Customer_ID { get; set; }
public string Customer_Name { get; set; }
public int SalesOrder_ID { get; set; }
public Nullable<int> FK_Customer_ID { get; set; }
public Nullable<System.DateTime> SalesOrderDelivery_Date { get; set; }
public string Product_Name { get; set; }
public Nullable<int> SalesOrder_Quantity { get; set; }
public Nullable<double> SalesOrder_Unit_Price { get; set; }
public Nullable<double> SalesOrder_Total { get; set; }
public int SalesOrderDetail_ID { get; set; }
public Nullable<int> FK_SalesOrder_ID { get; set; }
public Nullable<int> FK_Product_ID { get; set; }
public Customer_Data Customer_Data { get; set; }
public SalesOrderDetail SalesOrderDetail { get; set; }
public SalesOrder SalesOrder { get; set; }
}
View
#model IEnumerable<Theme_Hisaab.Models.CustomerLedger>
....
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Customer_ID)
</th>
<th>
#Html.DisplayNameFor(model => model.Customer_Name)
</th>
<th>
#Html.DisplayNameFor(model => model.SalesOrder_ID)
</th>
....
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Customer_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Customer_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.SalesOrder_ID)
</td>
....
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
Your list IEnumerable<CustomerLedger> CustomerLedger = null; is IEnumerable<CustomerLedger> type and also model used in view as #model IEnumerable<Theme_Hisaab.Models.CustomerLedger> so you need to pass same type in view from controller so make the query return type .AsEnumerable(). Also create and the in your select statement. At present you are selecting a anonymouse object type but you need to select CustomerLedger type. I don't know your exact database structure but I have show a way by which you can solve it
CustomerLedger = (from cus_data in db.Customer_Data
join so in db.SalesOrder on cus_data.Customer_ID equals so.SalesOrder_ID
join sd in db.SalesOrderDetail on so.SalesOrder_ID equals sd.SalesOrderDetail_ID
select new CustomerLedger
{
Customer_ID = cus_data.Customer_ID,
Customer_Name = cus_data.Customer_Name,
SalesOrder_ID = so.SalesOrder_ID,
FK_Customer_ID = so.K_Customer_ID,
SalesOrderDelivery_Date = so.SalesOrderDelivery_Date,
Product_Name = sd.SalesOrderDetail_ID,
SalesOrder_Quantity = sd.SalesOrderDetail_ID,
SalesOrder_Unit_Price = sd.SalesOrderDetail_ID,
SalesOrder_Total = sd.SalesOrderDetail_ID,
SalesOrderDetail_ID = sd.SalesOrderDetail_ID,
FK_SalesOrder_ID = sd.FK_SalesOrder_ID,
FK_Product_ID = sd.FK_Product_ID,
Customer_Data = sd.Customer_Data,
SalesOrderDetail = sd.SalesOrderDetail,
SalesOrder = sd.SalesOrder,
}).AsEnumerable();
But better way to create a ViewModel using this properties
public class MyViewModel
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int SalesOrderID { get; set; }
public int? FKCustomerID { get; set; }
public int SalesOrderDetailID { get; set; }
public double? SalesOrderUnitPrice { get; set; }
public double? SalesOrderTotal { get; set; }
public int? FKSalesOrderID { get; set; }
public int? FKProductID { get; set; }
}
Then model and select statement
IEnumerable<MyViewModel> CustomerLedger = null;
select new MyViewModel
{
CustomerID = cus_data.Customer_ID,
CustomerName = cus_data.Customer_Name,
SalesOrderID = so.SalesOrder_ID,
FKCustomerID = so.FK_Customer_ID,
SalesOrderDetailID = sd.SalesOrderDetail_ID,
SalesOrderUnitPrice = sd.SalesOrder_Unit_Price,
SalesOrderTotal = sd.SalesOrder_Total,
FKSalesOrderID = sd.FK_SalesOrder_ID,
FKProductID = sd.FK_Product_ID
}
and View
#model IEnumerable<Theme_Hisaab.Models.MyViewModel>

ViewModel Error : Object reference not set to an instance of an object [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I cannot understand why I am getting this error, could you please help me find what I am doing wrong ?
What i am trying to achieve with this ViewModel is because i have many records with the same CartId to use it as a parent and booking.Item.ItemName as a child.
Can you please advise if the way i am trying to do it is correct?
Controller:
public ActionResult MyBookings()
{
var myBookingList = SystemDB.Carts.Where(s => s.Booking.Login == strLoginName).OrderByDescending(s => s.RecordId).Take(10);
List<MyBookingsViewModel> result = new List<MyBookingsViewModel>();
foreach (var item in myBookingList)
{
MyBookingsViewModel model = new MyBookingsViewModel();
model.Carts.RecordId = item.RecordId;
model.Carts.CartId = item.CartId;
model.Carts.Booking.Item.ItemName = item.Booking.Item.ItemName;
model.Carts.Booking.UserFullName = item.Booking.UserFullName;
model.Carts.Booking.RequestDate = item.Booking.RequestDate;
model.Carts.StatusCode.StatusCodeName = item.StatusCode.StatusCodeName;
result.Add(model);
}
return View(result);
}
Model:
public class MyBookingsViewModel
{
public Cart Carts { get; set; }
public List<Booking> Bookings { get; set; }
}
public class Cart
{
[Key]
public int RecordId { get; set; }
public string CartId { get; set; }
public int Count { get; set; }
[ForeignKey("Booking")]
public int BookingId { get; set; }
public virtual Booking Booking { get; set; }
[ForeignKey("StatusCode")]
public int Stage { get; set; }
public virtual StatusCode StatusCode { get; set; }
public Cart()
{
this.Booking = new List<Booking>();
}
}
public class Booking
{
[DisplayName("BookingId")]
public int BookingId { get; set; }
[ForeignKey("Item")]
public int ItemId { get; set; }
public virtual Item Item { get; set; }
[DisplayName("Name")]
public string UserFullName { get; set; }
[DateStart]
[DisplayFormat(DataFormatString = "{0:dd/MM/yy hh:mm tt}", ApplyFormatInEditMode = true)]
public DateTime StartDate { get; set; }
[DateEnd(DateStartProperty = "StartDate")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yy hh:mm tt}", ApplyFormatInEditMode = true)]
public DateTime EndDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d MMM yyyy}", ApplyFormatInEditMode = true)]
public System.DateTime RequestDate { get; set; }
[DisplayName("Login")]
public string Login { get; set; }
[DisplayName("NetworkID")]
public string NetworkID { get; set; }
[DisplayName("Comments")]
public string Comments { get; set; }
}
View:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Carts.RecordId)
</td>
<td>
<a href="#Url.Action("ItemDetails", new {id=item.Carts.BookingId })" >
#Html.DisplayFor(modelItem => item.Carts.CartId)
</a>
#foreach(var booking in item.Bookings)
{
<li>#booking.Item.ItemName</li>
}
</td>
</tr>
}
Have a look at your model class definition
public class MyBookingsViewModel
{
public Cart Carts { get; set; }
public List<Booking> Bookings { get; set; }
}
and the following lines in your controller code
foreach (var item in myBookingList)
{
MyBookingsViewModel model = new MyBookingsViewModel();
model.Carts.RecordId = item.RecordId;
model.Carts.CartId = item.CartId;
model.Carts.Booking.Item.ItemName = item.Booking.Item.ItemName;
model.Carts.Booking.UserFullName = item.Booking.UserFullName;
model.Carts.Booking.RequestDate = item.Booking.RequestDate;
model.Carts.StatusCode.StatusCodeName = item.StatusCode.StatusCodeName;
result.Add(model);
}
You were trying to set model.Carts.RecordId while model.Carts is null. You need to initialize Carts property before doing so. The initialization should be done in the constructor to avoid code repetition. Change your model class definition to the following
public class MyBookingsViewModel
{
public MyBookingsViewModel()
{
this.Carts = new Cart();
}
public Cart Carts { get; set; }
public List<Booking> Bookings { get; set; }
}
UPDATE:
As per your comment regarding the error in this line:
model.Carts.Booking.Item.ItemName = item.Booking.Item.ItemName;
The problem is model.Carts.Booking is null when you set the value of model.Carts.Booking.Item. This line also has a similar problem:
model.Carts.StatusCode.StatusCodeName = item.StatusCode.StatusCodeName;
model.Carts.StatusCode is null when you set the value of model.Carts.StatusCode.StatusCodeName, so you need to add the similar thing to the Cart class definition in the constructor like below:
public class Cart()
{
public Cart()
{
this.Booking = new Booking();
this.StatusCode = new StatusCode();
}
}
and also in the Booking class definition
public class Booking()
{
public Booking()
{
this.Item = new Item();
}
}

Categories

Resources