MVC 5: Controller, Database and View have strange behaviour - asp.net

So I have this little "Restaurant" webapp going on where I'm trying to construct a View-page where an user can click on a created (restaurant) table (dropdown that refreshes automatically after clicking) and check what dishes are ordered on that table. At the bottom, the user will find the total price.
My view works 100% fine but ONLY if I have 1 table in the database. If I have multiple tables (restaurant tables) (created in my DropCreate-Seed method), the view will only show the dropdown with available tables, not the dishes inside of them.
What could cause this problem?
CODE
TABLE
public class Table
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual List<Dish> Dishes { get; set; }
}
SEED METHOD
context.Tables.Add(new Table { Id = 1 ,Name = "table1", Dishes = context.Dishes.ToList() });
context.Tables.Add(new Table { Id = 2, Name = "table2", Dishes = context.Dishes.ToList() });
context.Tables.Add(new Table { Id = 3, Name = "table3", Dishes = context.Dishes.ToList() });
context.SaveChanges();
TABLE CONTROLLER
public ActionResult Order(int? tableID)
{
//Create a ViewBag variable contained with all the tables (show name)
List<table> tableL = db.tables.ToList();
List<SelectListItem> tableSL = new List<SelectListItem>();
foreach (var table in tableL)
{
TableSL.Add(new SelectListItem { Text = table.Name.ToLower(), Value = table.Name.ToString() });
}
ViewBag.tableL = tableSL;
//At the start or at problems, get the first table and return it
if (tableID == null || db.tables.Find(tableID) == null)
{
return View(db.tables.First());
}
else
{
Table l = db.tables.Find(tableID);
return View(l);
}
}
VIEW
#model VBExamenTEST.Models.Table
#{
ViewBag.Title = "Order";
}
<h2>Order</h2>
#using (Html.BeginForm("Bedien", "Bedien", FormMethod.Post))
{
#Html.DropDownList("tableID", (List<SelectListItem>)ViewBag.TableL, new {onchange = "this.form.submit()" });
}
#if(Model != null)
{
double total = 0;
<table>
<tr>
#foreach(var g in Model.Dishes)
{
total += g.Price;
<td>
#Html.DisplayFor(Model=>g.Name)
</td>
}
</tr>
</table>
<p>Total:#total euro </p>
}
So my code works perfectly if I only have one table added in my DB, whenever I add more, only the dropdown shows up, the dishes are not shown on click, and the total equals 0.
Where can my problem be situated?

Related

Problem with getting the correct controller model

For the task I have to download several items from several xml documents (RssReader) then display random 4 elements on the page. I have already done all the code, the only problem is that the page displays the same 4 items, if I set the trap in the debuggeer in the view/controller everything loads correctly. I do not know what the problem may be, it's my beginnings in ASP.NET for all the clues to the code, thank you very much!
View code:
<table class="table">
#foreach (var item in Model)
{
<tr>
<td>
#item.Title
</td>
<td>
#item.PubDate
</td>
</tr>
}
</table>
Model Code:
public class RssItem
{
public string Title { get; set; }
public string PubDate { get; set; }
}
Controller Code:
public class PortfolioController : Controller
{
// GET: Portfolio
public ActionResult Index()
{
var linkList = new List<string> {
"https://news.google.com/rss?hl=pl&gl=PL&ceid=PL:pl",
"https://news.google.com/rss?hl=pl&gl=PL&ceid=PL:pl",
"https://news.google.com/rss?hl=pl&gl=PL&ceid=PL:pl",
"https://news.google.com/rss?hl=pl&gl=PL&ceid=PL:pl"
};
List<RssItem> rssItems = new List<RssItem>();
List<RssItem> randomRSS = new List<RssItem>();
foreach (string linkRss in linkList)
{
XElement xml = XElement.Load(linkRss);
var query = xml.Descendants("item").Select(item =>
new RssItem
{
Title = item.Element("title").Value,
PubDate = item.Element("pubDate").Value,
}).ToList();
foreach (var item in query)
{
rssItems.Add(item);
}
}
for (int i = 0; i < 4; i++)
{
Random random = new Random();
int randomInt = random.Next(rssItems.Count);
randomRSS.Add(rssItems[randomInt]);
}
return View(randomRSS);
}
}
Without traps in debugger:
With traps in view and controller (debugger mode):
Why do four requests? You can take the items from a single request and display random 4. But in order for Random to work it needs to be outside the for loop.
Random random = new Random();
for (int i = 0; i < 4; i++)
{
int randomInt = random.Next(rssItems.Count);
randomRSS.Add(rssItems[randomInt]);
}
But you could still end up with duplicates if you do not remove the rss from the list since random can create duplicates, see this answer for solutions
Random number generator with no duplicates

Retrieve data of Logged in user from other table through LINQ

This is my ViewModel where i've added two of my tables. Account_Detail (im getting login from this table). Basic_Detail (I need to retrieve data from this table after user logs in, through Session)
public class BasicAccountView
{
public Account_Details Account_Details { get; set; }
public Basic_Details Basic_Details { get; set; }
}
Here is my login code, I've got both Name and ID in their respective Session variables
public ActionResult Index(Account_Details log)
{
var obj = db.Account_Details.Where(u => u.Name.Equals(log.Name) && u.Password.Equals(log.Password)).FirstOrDefault();
Session["Account"] = log;
if (obj != null)
{
Session["loginid"] = obj.U_ID;
Session["name"] = obj.Name;
Session["email"] = obj.Email;
return RedirectToAction("Verify");
}
else
{
return View();
}
}
Login code is all okay and get going, even Session is working fine, they're retrieving Name of logged in user. Though, scenario is like, I need to join this Account and Basic table, so that I can get details of logged in user from Basic_Detail table. here is my join query, but it ain't working, showing nothing at all.
public ActionResult Verify()
{
var Result = (from o in db.Basic_Details
join od in db.Account_Details on o.User_ID equals od.U_ID
where o.FirstName == this.HttpContext.User.Identity.Name
select new BasicAccountView { Basic_Details = o, Account_Details = od }).ToList();
//var Result = (from o in db.Basic_Details
// join od in db.Account_Details on o.User_ID equals od.U_ID
// select new Basic_Details { FirstName = od.Name }).ToList();
return View(Result);
}
View of Verify Action
#model IEnumerable<Matrimonial.Models.BasicAccountView>
#{
ViewBag.Title = "Verify";
Layout = "~/Views/Shared/Main.cshtml";
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
#foreach(var item in Model)
{
<td>#item.Basic_Details.FirstName</td>
<td>#item.Basic_Details.LastName</td>
<td>#item.Basic_Details.MaritalStatus</td>
<td>#item.Basic_Details.Religion</td>
}
UPDATE - ISSUE RESOLVED
Just get Session["loginid"] into other variable and compare it to other table UserID from where you want to retrieve the data. I hope it'll help others with the same issue.
public ActionResult Verify()
{
BasicAccountView bav = new BasicAccountView();
int userId = (int)Session["loginid"];
var Result = from o in db.Basic_Details
join od in db.Account_Details on o.User_ID equals od.U_ID
where o.User_ID == userId
select new BasicAccountView { Basic_Details = o, Account_Details = od };
//var Result = (from o in db.Basic_Details
// join od in db.Account_Details on o.User_ID equals od.U_ID
// select new Basic_Details { FirstName = od.Name }).ToList();
return View(Result);
}
You should check the actual value of "this.HttpContext.User.Identity.Name", it may be the problem.
Furthermore, check whether the JOIN query returns any results (exclude the WHERE clause).
I hope it gave you a clue.

Having a difficulty passing value of objects in view asp.net MVC

I have joined two tables(Projects, Task_Distribution) and pass the values to View as viewbag. But I can't access the value in view(such as: #item.Project_Id) and if I write like #item it displays the result like This image
How can I access only the value?
here is my controller code:
public class TableController : Controller
{
// GET: Table
public ActionResult Table()
{
Database_testEntities1 db1 = new Database_testEntities1();
List<Project> p = new List<Project>();
List<Task_Distribution> t = new List<Task_Distribution>();
var query = (from PI in db1.Projects join TI in
db1.Task_Distribution on PI.Project_Id equals TI.Project_Id select new { PI.Project_Id, TI.Employee_Id }).ToList();
ViewBag.table = query;
return View();
}
}
And this is my view
#{
ViewBag.Title = "Table";
}
<h2>Table</h2>
<table>
#foreach (var item in ViewBag.table)
{
<tr>
<td>
#item
</td>
</tr>
}
</table>
Can you guys give me a solution, please?
See this part of your LINQ expression,
select new { PI.Project_Id, TI.Employee_Id }
You are projecting the result to an anonymous object. So what you have in the ViewBag is a list of these anonymous objects. When you loop through them and executes the code #item, razor will call the ToString method on that which renders the property name and values(which is what you are seeing)
You can create a view model to represent this data and do a projection using that
public class ProjectEmployeeVm
{
public int ProjectId { set;get;}
public int EmployeeId { set;get;}
}
Now in your LINQ expression,
select new ProjectEmployeeVm { ProjectId = PI.Project_Id,EmployeeId = TI.Employee_Id }
Now in your view,you can use cast your viewbag item to a list of this view model
#foreach (var item in ViewBag.table as List<ProjectEmployeeVm>)
{
<p>#item.ProjectId<p>
<p>#item.EmployeeId <p>
}
Also now since you have a view model, why not use that to transfer data to view instead of using dynamic view bag which is prone to errors.
var items = (from PI in db1.Projects join TI in
db1.Task_Distribution on PI.Project_Id equals TI.Project_Id
select new ProjectEmployeeVm { ProjectId = PI.Project_Id,
EmployeeId = TI.Employee_Id
}).ToList();
return View(items);
Now in your view,
#model List<ProjectEmployeeVm>
#foreach (var item in Model)
{
<p>#item.ProjectId<p>
<p>#item.EmployeeId <p>
}

ASP.Net MVC 3 ListBox Selected Items Collection Null

I have a pretty simple scenario and I'm sure I'm just missing something obvious. I'm trying to use a ListBox to grab multiple Id's and add them to my model, but no matter what I do, the collection is always null. Here's the code:
The model collections:
public IEnumerable<Model.UserProfile> TravelBuddies { get; set; }
public IEnumerable<int> SelectedTravelBuddies { get; set; }
I populate the TravelBuddies collection in my controller.
The view code:
<div class="module_content">
#if (Model.TravelBuddies.Count() > 0)
{
#Html.ListBoxFor(m => m.SelectedTravelBuddies, new MultiSelectList(Model.TravelBuddies, "Id", "FullName"))
}
else
{
<span>You don't currently have any travel buddies (people who were with you on this trip). Don't worry, you can add some to this trip later if you'd like.</span>
}
</div>
The select list is populated in my view. No problem there. But once I select multiple items and submit my form, the Model.SelectedTravelBuddies collection is always null. Am I missing something obvious? It's been a long night of coding.
Update: Added Controller Code
[HttpGet]
public ActionResult New()
{
Model.Trip trip = new Model.Trip();
ITripService tripService = _container.Resolve<ITripService>();
IUserAccountService userService = _container.Resolve<IUserAccountService>();
int userProfileId = userService.GetUserProfile((Guid)Membership.GetUser().ProviderUserKey).Id;
trip.TripTypes = new SelectList(tripService.GetTripTypes(), "Id", "Name");
trip.TravelBuddies = userService.GetTravelBuddies(userProfileId);
tripService.KillFlightLegTempStorage();
return View(trip);
}
[HttpPost]
public ActionResult New([Bind(Exclude = "TripTypes")] Model.Trip trip)
{
ITripService tripService = _container.Resolve<ITripService>();
if (!ModelState.IsValid)
{
tripService.KillFlightLegTempStorage();
return View(trip);
}
int tripId = tripService.CreateTrip(trip, (Guid)Membership.GetUser().ProviderUserKey);
tripService.KillFlightLegTempStorage();
return RedirectToAction("Details", "Trip", new { id = tripId });
}
Ok so you are binding to SelectedTravelBuddies. When your list is rendered, what is it's name? It's been a long night for me too :) want to make sure it matches the model. Also are you sure the list is in the form element so they are posted?

ASP.Net Razor View

I may be doing it wrong... so please correct me if i am.
I've pulled my Last.FM data from their RestAPI and cached it (to be refreshed only if the cache is greater than 30 minutes old), and from there i've loaded it into an enumerated list of tracks.
I'm attempting to drop that logic in the Razor display, and never managed to make it work with more than just the foreach and if (item.image...)..., adding in the logic to drop the divs has caused razor to loose track of the closing bracket for the foreach.
Am I making this too complicated?
<!-- lfm data -->
#* Iterate over the Last.FM data and display it in an attractive format *#
#foreach (var group in Model.Select((x, i) => new { Group = i / 4, Item = x })
.GroupBy(x => x.Group)) {
<div class="LFM-Data">
foreach(var x in group) {
if (x.item.image != null) {
<img src="#x.item.image.ToString()" class="lfm-artwork" alt="#x.item.album"/>
} else {
<img src="/Content/images/lfm/NoAlbumArt.jpg" class="lfm-artwork" alt="No Album Art Available" />
}
<p>#Html.Raw(x.item.name.ToString())</p>
}
</div>
}
after following Equiso's suggestion, i'm getting an odd scoping issue where either X is not in the current scope, or x does not contain a property for image...
#model IEnumerable<CCBlog.Classes.LastFmWrapper.Track>
and this is part of the LFM Wrapper class --- that i'm modeling the data after
public struct Track
{
public string artist { get; set; }
public string name { get; set; }
public string album { get; set; }
public string image { get; set; }
}
I call shenanigans!
If you are trying to display the items in groups of 4 you could do somethig like this
#foreach (var group in Model.Select((x, i) => new { Group = i / 4, Item = x })
.GroupBy(x => x.Group)) {
<div class="LFM-Data">
foreach(var x in group) {
if (x.Item.image != null) {
<img src="#x.Item.image.ToString()" class="lfm-artwork" alt="#x.Item.album"/>
} else {
<img src="/Content/images/lfm/NoAlbumArt.jpg" class="lfm-artwork" alt="No Album Art Available" />
}
<p>#Html.Raw(x.Item.name.ToString())</p>
}
</div>
}
or you could create a ViewModel that get the items grouped already.

Resources