ASP.NET Core MVC table keeps showing same number - c#

I am at a total loss. Everything seems correct. And when I look at the database, the correct number is being submitted. But when I go to list the data from the database, the Amount column in the database list is always the same number.
When you go to the deposit tab, the first number you put in is always the number that will be displayed. So if i enter $50, $50 will appear in the transaction tab. However, let's say if i go back and put $60. It will still say $50 in the transaction history tab, but in the database, it says $60. Why is it not displaying the number from the database?
Account controller:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using The_Bank_of_Cardinal.Areas.Identity.Data;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using The_Bank_of_Cardinal.Models;
namespace The_Bank_of_Cardinal.Controllers
{
[Authorize]
public class AccountController : Controller
{
private readonly TransactionConnection _tc;
private readonly UserManager<CardinalUser> userManager;
private readonly SignInManager<CardinalUser> signInManager;
private readonly DepositConnection _dc;
public AccountController(TransactionConnection tc, UserManager<CardinalUser> userManager, SignInManager<CardinalUser> signInManager, DepositConnection dc)
{
_tc = tc;
this.userManager = userManager;
this.signInManager = signInManager;
_dc = dc;
}
public IActionResult Index()
{
return View();
}
public IActionResult Transactions()
{
var results = _tc.TransactionHistory.ToList();
return View(results);
}
public IActionResult Test()
{
return View();
}
[HttpGet]
public IActionResult Deposit(string Id)
{
var resultss = _dc.AspNetUsers.Where(s => s.Id == Id).FirstOrDefault();
return View(resultss);
}
[HttpPost]
public IActionResult Deposit(DepositModel model, TransactionModel tm)
{
var resultss = _dc.AspNetUsers.Where(s => s.Id == model.Id).FirstOrDefault();
int test = model.AccountBalance + userManager.GetUserAsync(User).Result.AccountBalance;
tm.UserName = userManager.GetUserAsync(User).Result.UserName;
string name = tm.UserName;
tm.Description = "personal deposit";
tm.TransactionType = "Deposit";
tm.Amount = "$" + model.AccountBalance.ToString();
model.AccountBalance = test;
_tc.TransactionHistory.Add(tm);
_tc.SaveChanges();
_dc.AspNetUsers.Remove(resultss);
_dc.AspNetUsers.Add(model);
_dc.SaveChanges();
//_dc.AspNetUsers.
return Content("This is your info \n" +
$"Name: {name} \n" +
$"Description: {tm.Description} \n" +
$"type: {tm.TransactionType} \n" +
$"Amount {tm.Amount} \n");
}
public IActionResult Transfers()
{
return View();
}
}
}
Transaction view:
#model IEnumerable<The_Bank_of_Cardinal.Models.TransactionModel>
#{
ViewData["Title"] = "Transactions";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Transactions</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
#*<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.UserName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.TransactionType)
</th>
<th>
#Html.DisplayNameFor(model => model.Amount)
</th>
<th>
#Html.DisplayNameFor(model => model.Date)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.TransactionType)
</td>
<td>
#Html.DisplayFor(modelItem => item.Amount)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</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>
}
</tbody>
</table>*#
<div class="container">
#if (Model != null)
{
<table class="table table-dark">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Description</th>
<th scope="col">Transaction Type</th>
<th scope="col">Amount</th>
<th scope="col">Date</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.UserName)</td>
<td>#Html.DisplayFor(modelItem => item.Description)</td>
<td>#Html.DisplayFor(modelItem => item.TransactionType)</td>
<td>#Html.DisplayFor(modelItem => item.Amount)</td>
<td>#Html.DisplayFor(modelItem => item.Date)</td>
</tr>
}
</tbody>
</table>
}
</div>
Deposit view:
#model The_Bank_of_Cardinal.Models.DepositModel
#{
ViewData["Title"] = "Deposit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Deposit</h1>
<h4>DepositModel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Deposit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label hidden asp-for="Id" class="control-label"></label>
<input hidden asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AccountBalance" class="control-label">Amount</label>
<input asp-for="AccountBalance" class="form-control" value="0" />
<span asp-validation-for="AccountBalance" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Deposit" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Deposit model:
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using The_Bank_of_Cardinal.Areas.Identity.Data;
namespace The_Bank_of_Cardinal.Models
{
public class DepositModel
{
[Key]
public string Id { get; set; }
public int AccountBalance { get; set; }
}
}
Transaction model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace The_Bank_of_Cardinal.Models
{
public class TransactionModel
{
[Key]
public string UserName { get; set; }
public string Description { get; set; }
public string TransactionType { get; set; }
public string Amount { get; set; }
public DateTime Date { get; set; }
}
}
Deposit DbContext:
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace The_Bank_of_Cardinal.Models
{
public class DepositConnection : DbContext
{
public DepositConnection(DbContextOptions<DepositConnection> options) : base(options)
{
}
public DbSet<DepositModel> AspNetUsers { get; set; }
}
}
Transaction DbContext:
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace The_Bank_of_Cardinal.Models
{
public class TransactionConnection : DbContext
{
public TransactionConnection(DbContextOptions<TransactionConnection> options) : base(options)
{
}
public DbSet<TransactionModel> TransactionHistory { get; set; }
}
}

The class TransactionModel has for primary key the property UserName.
But you have several TransactionModel instances with the same UserName value. This is contradictory. Each TransactionModel primary key must be unique.
Change your TransactionModel class to something like:
public class TransactionModel
{
public int Id { get; set; } // This is the primary key.
public string UserName { get; set; }
public string Description { get; set; }
public string TransactionType { get; set; }
public decimal Amount { get; set; }
public DateTime Date { get; set; }
}
The property Id is your primary key. It will be automatically incremented. This is by convention. See: https://learn.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#configuring-a-primary-key
and https://learn.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=data-annotations#primary-keys
Side note: The type of the property Amount should rather be decimal than string, so this is changed in the example above. In the same spirit, an enum would maybe be a better choice for the TransactionType property.
You will need of course to modify the code using the class TransactionModel in order to take into account its new definition.

You're using #Html.XXXFor() incorrectly.
When you want to use HTML-helpers for HTML <form> input binding from a collection in your ViewModel you need to use for(), not foreach() and you need to the [int index] indexer in the For() expression.
When you need to bind a form object / form model and pass extra data to your view, use ViewData for the one-way data and Model for the two-way data.
I think that ASP.NET MVC and ASP.NET Core's view-model and form-binding system needs a re-think, as it's just plain wrong to require the ViewModel object to also be the bound form model. In my own projects I have my own extensions over ASP.NET Core to allow me to use separate types/objects cleanly.
I can't fix your ActionLink items though
<tbody>
#for( int i = 0; i < this.Model.Count; i++ ) {
<tr>
<td>
#Html.DisplayFor( m => m[i].UserName )
</td>
<td>
#Html.DisplayFor( m => m[i].Description )
</td>
<td>
#Html.DisplayFor( m => m[i].TransactionType )
</td>
<td>
#Html.DisplayFor( m => m[i].Amount )
</td>
<td>
#Html.DisplayFor( m => m[i].Date )
</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>
}
</tbody>

Related

Can not retrieve data from DB -> ERROR - >The entity or complex type ... cannot be constructed in a LINQ to Entities query

I have checked majority of several question but unfortunately, due to lack of enought experience, will not be able to solve this problem without your help.
I can not understand why this error happens. I think code is not wrong.
To see whole code in github
This is
UserController
using BookRental.Models;
using BookRental.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace BookRental.Controllers
{
public class UserController : Controller
{
private ApplicationDbContext db;
public UserController()
{
db = ApplicationDbContext.Create();
}
// GET: User/Index
public ActionResult Index()
{
var userList = (from u in db.Users
join m in db.MembershipTypes on u.membershipTypeId equals m.membershipTypesIdPK
select new UserViewModel
{
Id = u.Id,
fname = u.fname,
lname = u.lname,
email = u.Email,
phone = u.phone,
bdate = u.bdate,
userMemTypeId = u.membershipTypeId,
MembershipTypes = (ICollection<MembershipTypes>)db.MembershipTypes.ToList().Where(n => n.membershipTypesIdPK.Equals(u.membershipTypeId)),
disabled = u.disabled
}).ToList();
return View(userList);
}
UserViewModel
using BookRental.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace BookRental.ViewModel
{
public class UserViewModel
{
[Required]
public string Id { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string email { get; set; }
[DataType(DataType.Password)]
public string password { get; set; }
[DataType(DataType.Password)]
public string confirmPassword { get; set; }
public ICollection<MembershipTypes> MembershipTypes { get; set; }
[Required]
public int userMemTypeId { get; set; }
[Required]
public string fname { get; set; }
[Required]
public string lname { get; set; }
[Required]
public string phone { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM dd yyyy}")]
public DateTime bdate { get; set; }
public bool disabled { get; set; }
}
}
Index view
#model IEnumerable<BookRental.ViewModel.UserViewModel>
#using BookRental.Models
#{
ViewBag.Title = "Index";
}
<h2>Genre</h2>
#Html.Partial("_CreateButtonPartial")
<br />
<br />
<br />
<table class="table table-hover">
<thead class="thead-dark">
<tr class="row">
<th class="col">
#Html.DisplayNameFor(m => m.fname)
</th>
<th class="col">
#Html.DisplayNameFor(m => m.lname)
</th>
<th class="col">
#Html.DisplayNameFor(m => m.email)
</th>
<th class="col">
#Html.DisplayNameFor(m => m.bdate)
</th>
<th class="col">
#Html.DisplayNameFor(m => m.phone)
</th>
<th class="col">
#Html.DisplayNameFor(m => m.disabled)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr class="row">
<td class="col">
#Html.DisplayNameFor(item => item.fname)
</td>
<td class="col">
#Html.DisplayNameFor(item => item.lname)
</td>
<td class="col">
#Html.DisplayNameFor(item => item.email)
</td>
<td class="col">
#Html.DisplayNameFor(item => item.bdate)
</td>
<td class="col">
#Html.DisplayNameFor(item => item.phone)
</td>
<td class="col">
#Html.CheckBoxFor(m => item.disabled, new { #class = "disabled" })
</td>
<td class="col">
#Html.Partial("_TableButtonPartial", new IndividualButtonPartial { userId = item.Id})
</td>
</tr>
}
</tbody>
</table>
Error
System.NotSupportedException
HResult=0x80131515
Message=The entity or complex type 'BookRental.Models.UserViewModel' cannot be constructed in a LINQ to Entities query.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
The problem is explained here; The entity cannot be constructed in a LINQ to Entities query
If you project onto a mapped entity, what you basically do is partially load an entity, which is not a valid state. EF won't have any clue how to e.g. handle an update of such an entity in the future (the default behaviour would be probably overwriting the non-loaded fields with nulls or whatever you'll have in your object)
In your Identitymodels.cs, you're defining the UserViewModel as an Entity Framework entity which is incorrect because you already have a ApplicationUsers entity and from the name itself UsersViewModel, you expect it to be just a View Model.
To fix this, just remove this line from your IdentityModels.cs;
public System.Data.Entity.DbSet<BookRental.ViewModel.UserViewModel> UserViewModels { get; set; }

Cant populate table with images using razor

'IEnumerable' does not contain a definition for 'ImageName' and no accessible extension method 'ImageName' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?
Is the current error I am getting, However the way im going about this seems to be wrong if anyone can help or point me in the right direction it would be appreciated. (Aslo I am using .net core 2.1 since my school computers do not support later versions :/)
Here is the view:
#model IEnumerable<Lab2Phase1.Models.Car>
#{
ViewData["Title"] = "Index";
}
<strong>Index</strong>
<p>
<a asp-action="Create">Create New</a>
</p>
<div class="col-md-8">
<form action="/Cars" method="post">
#Html.TextBox("search")
<input type="submit" />
</form>
</div>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Id)
</th>
<th>
#Html.DisplayNameFor(model => model.Model)
</th>
<th>
#Html.DisplayNameFor(model => model.TopSpeed)
</th>
<th>
#Html.DisplayNameFor(model => model.ImageName)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Model)
</td>
<td>
#Html.DisplayFor(modelItem => item.TopSpeed)
</td>
<td>
<img src="~/Content/images/#Html.DisplayFor(modelItem => modelItem.ImageName)" style="height:200px;width:200px;"/>
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id }, new { onclick = "return confirm('Are you sure to delete?')" })
</td>
</tr>
}
</tbody>
</table>
Here is the controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Lab2Phase1.Models;
using Microsoft.AspNetCore.Mvc;
using Lab2Phase1.CarsContext;
using System.Collections.Specialized;
using System.Drawing;
namespace Lab2Phase1.Controllers
{
public class CarsController : Controller
{
EFDataContext _dbContext = new EFDataContext();
public IActionResult Cars()
{
var data = this._dbContext.Cars.ToList();
return View(data);
}
[HttpPost]
public IActionResult Cars(string search)
{
Console.WriteLine("boot");
//search = Request.Form["search"].ToString();
var data = _dbContext.Cars.Where(c => c.Model.Contains(search));
return View(data);
}
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create([Bind("Id,Model,TopSpeed,ImageName")]Car model)
{
ModelState.Remove("Id");
model.Model = Request.Form["Model"];
model.TopSpeed = Request.Form["TopSpeed"];
model.ImageName = Request.Form["ImageName"];
if (ModelState.IsValid)
{
_dbContext.Cars.Add(model);
_dbContext.SaveChanges();
return RedirectToAction("cars");
}
return View();
}
public IActionResult Edit(int id)
{
Car data = _dbContext.Cars.Where(p => p.Id == id).FirstOrDefault();
return View("Create", data);
}
[HttpPost]
public IActionResult Edit(Car model)
{
ModelState.Remove("Id");
model.Id = Int32.Parse(Request.Form["Id"]);
model.Model = Request.Form["Model"];
model.TopSpeed = Request.Form["TopSpeed"];
model.ImageName = Request.Form["ImageName"];
if (ModelState.IsValid)
{
_dbContext.Cars.Update(model);
_dbContext.SaveChanges();
return RedirectToAction("cars");
}
return View("Create", model);
}
public IActionResult Delete(int id)
{
Car data = _dbContext.Cars.Where(p => p.Id == id).FirstOrDefault();
if (data != null)
{
_dbContext.Cars.Remove(data);
_dbContext.SaveChanges();
}
return RedirectToAction("cars");
}
}
}
Here's the model:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Lab2Phase1.Models
{
public class Car
{
[Key]
public int Id { get; set; }
public string Model { get; set; }
public string TopSpeed { get; set; }
public string ImageName { get; set; }
}
}
<img src="~/Content/images/#Html.DisplayFor(modelItem => modelItem.ImageName)" style="height:200px;width:200px;"/>
should be
<img src="~/Content/images/#(item.ImageName)" style="height:200px;width:200px;"/>
Assuming your ImageName is a file name with extention, available in that path.

EFCore+Razor Pages: nested foreach loop iterating over .included dataset returning zero results

I am attempting to make a DotnetCore C# MVC Razor Page created by EF core show related table data and appear to either be having a problem with LINQ .include in my pagemodels OnGetAsync method or when trying to show the included contents in the Razor page.
Any assistance would be appreciated. Please let me know if I can provide any more relevant information. I've only been doing EFCore/RazorPages/Mvc/C# for a couple months now, so please be kind!
Here is the index.cshtml.cs page where I include childtable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Appname.Models;
namespace Appname.Pages.Request
{
public class IndexModel : PageModel
{
private readonly Appname.Models.dbContext _context;
public IndexModel(Appname.Models.dbContext context)
{
_context = context;
}
public IList<ParentTable> ParentTable { get;set; }
public async Task OnGetAsync()
{
ParentTable = await _context.ParentTable
.Include(w => w.ChildTable)
.ToListAsync(); //Output to an async list
}
}
}
}
Here is the Index.cshtml razor page where the nested foreach loop iterating over Model.ParentTable[0].ChildTable never has its conditions satisfied because Model.ParentTable[0].ChildTable has a count of zero when inspected during debugging and therefore no data for ChildField1 or ChildField2 is displayed:
#page
#model Appname.Pages.Request.IndexModel
#{
ViewData["Title"] = "Index";
}
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.ParentTable[0].ParentField1)
</th>
<th>
#Html.DisplayNameFor(model => model.ParentTable[0].ParentField2)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.ParentTable)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ParentField1)
</td>
<td>
#Html.DisplayFor(modelItem => item.ParentField2)
</td>
<td>
<table class="table">
<tr>
<th>Child Field 1</th>
<th>Child Field 2</th>
</tr>
#foreach (var relatedItem in Model.ParentTable[0].ChildTable)
{
<tr>
<td>
#Html.DisplayFor(modelItem => relatedItem.ChildField1)
</td>
<td>
#Html.DisplayFor(modelItem => relatedItem.ChildField2)
</td>
</tr>
}
</table>
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.ParentTableid">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.ParentTableid">Details</a>
</td>
</tr>
}
</tbody>
</table>
Here is the ParentTable model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Appname.Models
{
public partial class ParentTable
{
[Key]
public long ParentTableid { get; set; }
public string ParentField1 { get; set; }
public string ParentField2 { get; set; }
public ICollection<ChildTable> ChildTable { get; set; }
}
}
...And the ChildTable model, using non-standard ID naming conventions for EF Core because that's how the field was designed in the database this is being written to work with long ago (not sure if this is part of the problem or if I have my key fields set up wrong):
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Appname.Models
{
public partial class ChildTable
{
public long nonstandardidfield { get; set; }
public string ChildField1 { get; set; }
public string ChildField2 { get; set; }
[ForeignKey("nonstandardidfield")]
public ParentTable ParentTable { get; set; }
}
}
Thank you for your time.
It looks to me that you are only every iterating over the ChildTable items of the first Model.
Change this:
#foreach (var relatedItem in Model.ParentTable[0].ChildTable)
{
<tr>
<td>
#Html.DisplayFor(modelItem => relatedItem.ChildField1)
</td>
<td>
#Html.DisplayFor(modelItem => relatedItem.ChildField2)
</td>
</tr>
}
To:
#foreach (var relatedItem in item.ChildTable)
{
<tr>
<td>
#Html.DisplayFor(ri => relatedItem.ChildField1)
</td>
<td>
#Html.DisplayFor(ri => relatedItem.ChildField2)
</td>
</tr>
}

MVC 5 EF 6 - How to Search a Table Using Related Table Object Criteria

I need to display a resulting table of PO Requests which includes the PO Items (this part I figured out) and provide search functionality for all items displayed (this part I got mostly figured out).
Using the code below, which is a slightly stripped down version, I am able to display the data I need and I am able to search for nearly all I need, as long as it is data from the PORequests model (this is the "parent model"). When I try to search using the "child model," POItems, the actual objects (ID, Description, etc.) are not accessible. This was built using DatabaseFirst model and EF6.x DbContextGenerator.
//POItemData ViewModel
using FinanceSearch.Models;
namespace FinanceSearch.ViewModels
{
public class POItemData
{
public PagedList.IPagedList<PORequest> PORequests { get; set; }
public PagedList.IPagedList<POItem> POItems { get; set; }
}
}
//POItems Model
namespace FinanceSearch.Models
{
using System;
using System.Collections.Generic;
public partial class POItem
{
public int ID { get; set; }
public int Amount { get; set; }
public string Description { get; set; }
public virtual PORequest PORequest { get; set; }
}
}
//PORequest Model
namespace FinanceSearch.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class PORequest
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public PORequest()
{
this.POAttachments = new HashSet<POAttachment>();
this.POItems = new HashSet<POItem>();
}
//other relevant stuff
public virtual ICollection<POItem> POItems { get; set; }
}
}
//Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using FinanceSearch.Models;
using PagedList;
using System.Web.UI.WebControls;
using System.Data.Entity.SqlServer;
using FinanceSearch.ViewModels;
namespace FinanceSearch.Controllers
{
public class PORequestsController : Controller
{
private Finance db = new Finance();
public ActionResult Index(int? id, int? page, string sortOrder, string currentFilter, string poNumber,
string AppropNumber, string ContractNumber, string ItemDescription)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.POSortParm = String.IsNullOrEmpty(sortOrder) ? "PONumber_desc" : "";
ViewBag.AppropNumberSortParm = sortOrder == "AppropNumber" ? "AppropNumber_desc" : "AppropNumber";
ViewBag.ContractNumberSortParm = sortOrder == "ContractNumber" ? "ContractNumber_desc" : "ContractNumber";
if (poNumber != null)
{
page = 1;
}
else
{
ponumber = currentFilter;
}
//int pageSize = 3;
int pageNumber = (page ?? 1);
var viewModel = new POItemData();
viewModel.PORequests = db.PORequests
.Include(i => i.POItems)
.OrderBy(i => i.ID).ToPagedList(pageNumber, 5);
if (!String.IsNullOrEmpty(poNumber))
{
viewModel.PORequests = viewModel.PORequests.Where(s => s.PONumber.Contains(ponumber)).ToPagedList(pageNumber, 5);
}
if (!string.IsNullOrEmpty(AppropNumber))
{
viewModel.PORequests = viewModel.PORequests.Where(x => x.AppropNumber.Contains(AppropNumber)).ToPagedList(pageNumber, 5);
}
if (!string.IsNullOrEmpty(ContractNumber))
{
viewModel.PORequests = viewModel.PORequests.Where(x => x.ContractNumber.Contains(ContractNumber)).ToPagedList(pageNumber, 5);
}
if (!string.IsNullOrEmpty(ItemDescription))
{
}
In the ItemDescription if statement, something like the following would be nice:
if (!string.IsNullOrEmpty(ItemDescription))
{
viewModel.PORequests = viewModel.PORequests.Where(x => x.POItems.Description.Contains(ItemDescription)).ToPagedList(pageNumber, 5);
}
The x.POItems.Description part doesn't exist in this sense. Apparently related to it being a list. Continuing remainder of code...
switch (sortOrder)
{
case "PONumber_desc":
viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.PONumber).ToPagedList(pageNumber, 5);
break;
case "AppropNumber":
viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.AppropNumber).ToPagedList(pageNumber, 5);
break;
case "AppropNumber_desc":
viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.AppropNumber).ToPagedList(pageNumber, 5);
break;
case "ContractNumber":
viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.ContractNumber).ToPagedList(pageNumber, 5);
break;
case "ContractNumber_desc":
viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.ContractNumber).ToPagedList(pageNumber, 5);
break;
default:
viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.PONumber).ToPagedList(pageNumber, 5);
break;
}
return View(viewModel);
}
In the code above, I included my paging and sorting stuff as well, because in the tutorials and answers I have come across, it appears to make a difference in how it all turns out, and is required for this project.
Below is the Index/View I am using to display the results:
//View (Index)
#model FinanceSearch.ViewModels.POItemData
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "PORequests";
}
<h2>Finance</h2>
#*<p>
#Html.ActionLink("Create New", "Create")
</p>*#
<p>
<button class="btn btn-default" data-toggle="collapse" href="#MainFilter" #*data-target="#MainFilter"*# aria-multiselectable="true" aria-expanded="true">Filter By...</button>
</p>
#*<div id="accordion" role="tablist" aria-multiselectable="true">*#
#using (Html.BeginForm("Index", "PORequests", FormMethod.Get))
{
<div id="MainFilter" class="collapse">
<table class="table-responsive">
<tr>
<td>
Item:
</td>
<td>
#Html.TextBox("ItemDescription", ViewBag.CurrentFilter as string) //this is where the user would search items using a string
</td>
</tr>
<tr>
<td>
PO #:
</td>
<td>
#Html.TextBox("PONumber", ViewBag.CurrentFilter as string)
</td>
</tr>
</table>
<br />
<p>
<button class="btn btn-primary btn-sm" data-parent="#MainFilter" data-toggle="collapse" href="#SubFilterPOInfo" #*data-target="#SubFilterPOInfo"*#>Filter by PO Info...</button>
</p>
<div id="SubFilterPOInfo" class="collapse">
<table class="table-responsive">
<tr>
<td>
AppropNumber:
</td>
<td>
#Html.TextBox("AppropNumber", ViewBag.CurrentFilter as string)
</td>
</tr>
<tr>
<td>
Contract Number:
</td>
<td>
#Html.TextBox("ContractNumber", ViewBag.CurrentFilter as string)
</td>
</tr>
</table>
</div>
}
<div style="overflow-x: scroll">
<table class="table" style="white-space:nowrap">
<tr>
<th></th>
<th></th>
<th>
#Html.ActionLink("PONumber", "Index", new { sortOrder = ViewBag.POSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("AppropNumber", "Index", new { sortOrder = ViewBag.AppropNumberSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("ContractNumber", "Index", new { sortOrder = ViewBag.ContractNumberSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
</tr>
#foreach (var item in Model.PORequests)
{
<tr>
<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>
<td>
//I am able to list the related items in the PORequests table
#foreach (var poitem in item.POItems)
{
#poitem.Description<br />
}
</td>
<td>
#Html.DisplayFor(modelItem => item.PONumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.AppropNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.ContractNumber)
</td>
</tr>
}
</table>
</div>
<br />
//paging and sorting stuff
Page #(Model.PORequests.PageCount < Model.PORequests.PageNumber ? 0 : Model.PORequests.PageNumber) of #Model.PORequests.PageCount
#Html.PagedListPager(Model.PORequests, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
To summarize:
I don't seem to comprehend how to use the variable ItemDescription to search within the POItems list, and get the PORequest table, which includes the POItem table as a related object, to display the results. My other searches all function as expected.
I have searched, on this site in particular, but any of the similar questions involve the view end of it just displaying each item in the list, which I am able to do, or creating/editing functionality, or, perhaps, they are beyond my understanding of MVC enough where they didn't appear to be a solution.
Here are a few such examples:
MVC Code First: One-to-many relationship between own model and SimpleMembership user
EntityFramework 6. How to get related objects?
https://stackoverflow.com/questions/26372533/add-the-list-of-object-to-parent-object-using-mvc-5-and-ef-6
Any help would be greatly appreciated.
Drill down to the items in the search expression:
if (!string.IsNullOrEmpty(ItemDescription))
{
viewModel.PORequests = viewModel.PORequests.Where(x => x.POItems
.Any(i => i.Description.Contains(ItemDescription)))
.ToPagedList(pageNumber, 5);
}

Filling a table or list with data from SQL (entity framework)

I cant get data to my table/list, I was trying to follow few videos and answers from stack overflow, but no data shows in tables...
This is my "Klubovi" class, "KluboviContext" class and "KluboviController":
"Klubovi" class, "KluboviContext" classes are in Models.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace filltabletest.Models
{
public class Klubovi
{
public virtual int Id { get; set; }
public virtual string ImeKluba { get; set; }
public virtual string KratkoIme { get; set; }
public virtual string Sport { get; set; }
public virtual string League { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using filltabletest.Models;
using System.Data.Entity;
namespace filltabletest.Models
{
public class KluboviContext : DbContext
{
public DbSet<Klubovi> KluboviPkg { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.SqlClient;
using filltabletest.Models;
namespace filltabletest.Controllers
{
public class KluboviController : Controller
{
//
// GET: /Klb/
private KluboviContext db = new KluboviContext();
public ActionResult Index()
{
var KluboviItems = db.KluboviPkg;
return View(KluboviItems.ToList());
}
}
}
View:
#model IEnumerable<filltabletest.Models.Klubovi>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml"; }
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create") </p> <table>
<tr>
<th>
#Html.DisplayNameFor(model => model.ImeKluba)
</th>
<th>
#Html.DisplayNameFor(model => model.KratkoIme)
</th>
<th>
#Html.DisplayNameFor(model => model.Sport)
</th>
<th>
#Html.DisplayNameFor(model => model.League)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ImeKluba)
</td>
<td>
#Html.DisplayFor(modelItem => item.KratkoIme)
</td>
<td>
#Html.DisplayFor(modelItem => item.Sport)
</td>
<td>
#Html.DisplayFor(modelItem => item.League)
</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> }
<connectionStrings>
<add name="KluboviContext" connectionString="Data Source=ZWERINJAK;Initial Catalog=OkladeNEW2;User ID=sa;Password=sa" providerName="System.Data.SqlClient" />
</connectionStrings>
Klubovi Db:
Image:Klubovi db
Result:
Image: Result from code
Can someone please help me resolve what to do?

Categories