How to join database tables in my website? - c#

Here is my code:
albums.cshtml
#page
#using Project.Models
#model Project.Pages.AlbumsModel
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Albums</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Album ID</th>
<th>Artist ID</th>
<th>Artist name</th>
<th>Album title</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (Album album in Model.Albums)
{
<tr>
<td>#album.AlbumId</td>
<td>#album.ArtistId</td>
<td>#Html.DisplayFor(modelArtists => album.Artist.Name)</td>
<td>#album.Title</td>
<td><a asp-page="/Albums/Details" asp-route-id="#album.AlbumId">Details</a></td>
<td><a asp-page="/Albums/Edit" asp-route-id="#album.AlbumId">Edit</a></td>
<td><a asp-page="/Albums/Delete" asp-route-id="#album.AlbumId">Delete</a></td>
<td><a asp-page="/Albums/AlbumTracks" asp-route-id="#album.AlbumId">Tracks</a></td>
</tr>
}
</tbody>
</table>
</div>
<div class="row">
<p>Enter a title & ArtistID for a new album: </p>
<form method="POST">
<div><input asp-for="Album.Title" /></div>
<div><input asp-for="Album.ArtistId" /></div>
<input type="submit" />
</form>
</div>
<div>
<a asp-page="/Index">Home</a>
</div>
AlbumTracks.cshtml
#page
#using Project.Models
#model Project.Pages.AlbumTracksModel
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Tracks</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Track name</th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (Track track in Model.Tracks)
{
<tr>
<td>#track.TrackId</td>
<td>#track.Name</td>
</tr>
}
</tbody>
</table>
</div>
#* <div class="row">
<p>Enter a name & TrackID for a new track: </p>
<form method="POST">
<div><input asp-for="Track.Name" /></div>
<div><input asp-for="Track.TrackId" /></div>
<input type="submit" />
</form>
</div> *#
<div>
<a asp-page="/Index">Home</a>
</div>
AlbumTracks.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Project.Models;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Project.Pages
{
public class AlbumTracksModel : PageModel
{
private Chinook db;
public AlbumTracksModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<Track> Tracks { get; set; }
public void OnGetAsync()
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album);
}
}
}
At the moment I'm displaying all tracks from every album in AlbumTracks.cshtml, instead of just the one selected by the user on album.cshtml. I've read this repeatedly, but I'm struggling to work out the syntax for AlbumTracks.cshtml, and maybe I need something more in AlbumTracks.cshtml.cs?
I think maybe I need to use something like this to join the tables:
if (item.AlbumID == Model.AlbumID)
Any pointers please? TIA.
Edit: GitHub repo

At the moment I'm displaying all tracks from every album in AlbumTracks.cshtml, instead of just the one selected by the user on album.cshtml.
Are you sure what you describe is correct? You display all the tracks from all the albums by using the following code:
Tracks = db.Tracks.Include(a => a.Album);
I think what you want is that you can display the selected album's tracks when click the Tracks link in albums.cshtml:
<td><a asp-page="/Albums/Album Tracks" asp-route-id="#album.AlbumId">Tracks</a></td>
If what I said is correct, you need firstly add id parameter to your /Albums/AlbumTracks method and modify the linq like below:
public class AlbumTracksModel : PageModel
{
private Chinook db;
public AlbumTracksModel(Chinook injectedContext)
{
db = injectedContext;
}
public IEnumerable<Track> Tracks { get; set; }
public void OnGetAsync(int id)
{
ViewData["Title"] = "Chinook Web Site - Tracks";
Tracks = db.Tracks.Include(a => a.Album).Where(a=>a.AlbumId==id);
}
}
AlbumTracks.cshtml:
#page
#using Project.Models
#model Project.Pages.AlbumTracksModel
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row">
<h1 class="display-2">Tracks</h1>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Track name</th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (Track track in Model.Tracks)
{
<tr>
<td>#track.TrackId</td>
<td>#track.Name</td>
</tr>
}
</tbody>
</table>
</div>
Result:

maybe try:
foreach (var track in Model.Tracks)
{
if(item.AlbumID == Model.AlbumID)
{
<tr>
<td>#track.TrackId</td>
<td>#track.Name</td>
</tr>
}
}
could you maybe post your models?
I had something similar in my app, I created 2 models e.g. 1 for tracks and 1 for albums.
then in your Album model make a list Tracklist and in your track model make a property AlbumId.
In your trackcontroller, upon creating a track you could have something like
var albums = _context.Albums.toList // or any other way to retrieve the albums from the DB.
foreach (var item in albums)
if (track.AlbumId = item.Id)
{
item.Tracklist.add(Track)
}
I'm still kinda new to this so hope this works!

Related

In an MVC Data List what is the best way to toggle conditions in a SQL Query

Please excuse me, I am new to MVC and Entity Framework but have been unable find information to solve my problem.
Problem 1 is that I am trying add a where statement to my model and show only active players. You can see my two separate procedures in my controller, but they both yield the same results.
public IActionResult ActivePlayers()
{
var model = _playerRepository.GetAllPlayers();
return View("Players",model.Where(d => d.IsActive = true));
}
public IActionResult AllPlayers()
{
var model = _playerRepository.GetAllPlayers();
return View("Players", model);
}
My second problem is I am having a hard time figuring how to toggle between All Players and Active ones from the View.
I tried the following, but quickly realized that it wouldn't work since the page is re-rendered after calling the controller. - Note, I was using jQuery to toggle viability.
<div>
<label id="lblShowAll" style="color:green;font-style:italic;font-weight:bold;"
>Showing Active Players</label>
<label id="lblLimitList" style="color:green;font-style:italic;font-weight:bold;display:none;"
>Showing All Players</label>
<br />
<a id="ShowAll" class="btn btn-link"
asp-controller="admin" asp-action="allPlayers">Show All Players</a>
<a id="LimitList" class="btn btn-link" style="display:none;"
asp-controller="admin" asp-action="activePlayers">Limit List (Active Players)</a>
</div>
I'm not sure it matters but this is what my data list looks like in the View.
<div class="container" id="players">
<br />
<div style="width:90%; margin:0 auto;">
<table id="playerList" class="table table-striped table-bordered dt-responsive nowrap"
width="100%" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>State</th>
<th>Telephone</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
#foreach (var player in Model)
{
<tr>
<th>#player.Name</th>
<th>#player.Address</th>
<th>#player.City</th>
<th>#player.State</th>
<th>#player.Telephone</th>
<th>
<a class="btn btn-outline-info m-1"
asp-controller="admin" asp-action="editPlayer" asp-route-id="#player.PlayerId">
Edit</a>
</th>
<th>
<a class="btn btn-outline-danger m-1">Delete</a>
</th>
</tr>
}
</tbody>
</table>
</div>
</div>
Thanks in advance!

Row to send a List<Object> from Razor page to Update?

I need to send a List back to my controller and update the values on my repository.
But after load the view with the values, update it and click the submit button, I don't know how to get the list with the update values and call the update method from the repository.
I'm using .Net 4.7.2.
HomeController:
[HttpGet]
public ActionResult Nota(string Concurso)
{
List<InscricoesModel> model = new List<InscricoesModel>();
InscricoesRepository repository = new InscricoesRepository();
model = repository.GetAprovadosPrimeiraFase(new Guid(Concurso));
return View("Nota",model);
}
[HttpPost]
public void UdateNotas(List<InscricoesModel> model)
{
InscricoesRepository repository = new InscricoesRepository();
foreach(InscricoesModel item in model)
{
repository.Update(item);
}
}
Nota.cshtml:
#model List<ConcursoBolsaSegundaFase.Model.InscricoesModel>
<h1>Classificados 2ª Fase</h1>
<hr />
<p>Exportado em #DateTime.Now</p>
<div style="margin-top:15px">
#* TABELA RESULTADO *#
<div id="notasAprovadosSegundaFase" style="margin-top:10px">
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var linha in Model)
{
<tr>
<td>#linha.Inscricao</td>
<td>#linha.Nome</td>
<td>#linha.NotaPrimeiraFase</td>
<td>
<select>
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
</div>
</div>
The UpdateNotas method in my controller never recive a value, i don't know how to send the list from the view to my controller.
In MVC, the name of the input will be binded to the variable in the controller. In your case, your input has no name. I suggest you look at the html helpers.
This would bind your values properly.
for (int i = 0;i<Model.Count;i++)
{
Html.TextBoxFor(model => Model[i].NotaSegundaFase)
}
In this case, only NotaSegundaFase would be sent back to the controller.
You can use #Html.HiddenFor() to hold the data on the view and bind to controller on Post.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-striped table-bordered table-sm table-responsive">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(model => Model[i].Inscrição)
#Html.HiddenFor(model => Model[i].Nome)
#Html.HiddenFor(model => Model[i].NotaPrimeiraFase)
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
#*do this similary for other property *#
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
As far as I understood,you want to post DropDownList value only.
if you decide to update other fields just add the Html.Editor into the loop like following.
#Html.Editor("[" + i + "].Inscricao")
#Html.Editor("[" + i + "].Nome")
I hope this will help.
#using (Html.BeginForm("UdateNotas", "Home", Model, FormMethod.Post))
{
<table class="table table-bordered" id="tblNotaAprovadosSegundaFase">
<thead>
<tr>
<th>Inscrição</th>
<th>Nome</th>
<th>Nota Primeira Fase</th>
<th>Fez Carta</th>
<th>Nota Segunda Fase</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Model[i].Inscrição</td>
<td>#Model[i].Nome</td>
<td>#Model[i].NotaPrimeiraFase</td>
<td>
<select name="[#i].NotaSegundaFase">
<option value="false">Não</option>
<option value="true">Sim</option>
</select>
</td>
<td><input type="text" value="#linha.NotaSegundaFase"></td>
</tr>
}
}
</tbody>
</table>
<button type="submit" class="btn btn-success">Salvar</button>
}
Note : don't change anything in the controller. model binder should resolve everything from the request.

How to post data to razor page code behind asp.net core

I want to implement a bulk operation function, but I cannot post my data to the razor page code behind, anyone can help? Please check my code below
<form method="post" asp-page="./Index">
<div class="row">
<div class="col-md-12">
<table class="table table-hover table-bordered" style="margin-top:15px;">
<thead>
<tr class="info">
<th></th>
<th>
<a asp-page="./Index" asp-route-sortOrder="#Model.NumberSort">
#Html.DisplayNameFor(model => model.Products[0].Number)
</a>
</th>
<th>
#Html.DisplayNameFor(model => model.Products[0].Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Products)
{
<tr>
<td>
#Html.CheckBoxFor(modelItem => item.Checked)
</td>
<td class="success">
#Html.DisplayFor(modelItem => item.Number)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a asp-page="./Details" asp-route-id="#item.ID" class="btn btn-info">details</a>
<a asp-page="./Edit" asp-route-id="#item.ID" class="btn btn-warning">edit</a>
<a asp-page="./Delete" asp-route-id="#item.ID" class="btn btn-danger">delete</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-10">
#{
var items = Model.Products.Where(x => x.Checked);
}
<input type="submit" name="bulkUpload" value="bulk upload" asp-route-data="#items"/>
</div>
</div>
</form>
public async Task OnPostAsync(List<Product> upload)
{
}
You need to render your products in such way that the Modelbinder will be able to pick them up on form submit and pass them into the codebehind.
Something like this (done by hand so it might not compile at first):
#{
for (int i = 0; i < Model.Products.Count; i++)
{
<input type="checkbox" asp-for="Model.Produtcs[i].Checked" />
#Model.Products[i].Number
#Model.Products[i].Name
}
}
This will render HTML like
<input type="checkbox" name="Products[0].Checked" />
<input type="checkbox" name="Products[1].Checked" />
<input type="checkbox" name="Products[2].Checked" />
And it should get back to your OnPostAsync. If not then try changing
public async Task OnPostAsync(List<Product> upload)
to
public async Task OnPostAsync(YourModel model)
What ever your full model is named.
This is then redundant:
#{
var items = Model.Products.Where(x => x.Checked);
}

ASP.Net MVC random, Controllers and views

I have been having trouble creating a ASP.NET MVC program that will randomly select a student and randomly select a question and for some reason I cant get it to work in the .cshtml file. Am I doing something wrong? Also i get this Error
"The model item passed into the dictionary is of type 'QuizProgramMVC.Models.Student', but this dictionary requires a model item of type 'QuizProgramMVC.Models.StudentQuestion'."`using QuizProgramMVC.Models;
Controller
public class QuizController : Controller
{
public QuizController TheQuiz { get; set; }
// GET: Quiz
public ActionResult Index()
{
StudentQuestion sq = new StudentQuestion();
return View(sq);
}
public ActionResult QuizProgram()
{
Student program = new Student();
return View(program);
}
}
View
#model QuizProgramMVC.Models.StudentQuestion
#using QuizProgramMVC.Models;
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>QuizProgram</title>
</head>
<body>
<div>
<h1>Quiz Program</h1>
<div class="row">
<div class="col-md-6">
<table class="table table-condensed">
<thead>
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody>
#foreach (Question q in Model.Questions)
{
<tr>
<td>
#q.Quest
</td>
<td>
#q.Answer
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<br/>
<div class="row">
<div class="col-md-6">
<table class="table table-condensed">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
#foreach (Student s in Model.Students)
{
<tr>
<td>
#s.FirstName
</td>
<td>
#s.LastName
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<br/>
#using (Html.BeginForm())
{
<div>
Type Answer: <input id="param1" name="param1" type="text" />
<br />
<input type="submit" value="Submit" />
</div>
}
</div>
</body>
</html>
The problem is you are calling the same view page with different model.
public ActionResult QuizProgram()
{
Student program = new Student();//Here you need to pass the StudentQuestion to the view.
return View(program);
}
Calling the above View Page(.cshtml) via QuizProgram() throws an error because in that view page you defined the model as
#model QuizProgramMVC.Models.StudentQuestion
It does not allow other ViewModels because it is strongly-typed View.

Linq refer to list of objects which were passed with an include statement

Here is how I pass a model to a view:
public ActionResult Public()
{
db = new Entities();
var regions = db.Regions.Include(d => d.Days);
return View(regions.ToList());
}
Now I want to be able to create a foreach in the view which will access the collection of days I included in regions for that particular region. Is there a way to do this through link or should I create a seperate ViewModel that contains fields separately for Regions and for Days?
part of view code:
...
#for(int i = 1; i < Model.Count(); i ++){
<div id="_page_#i" class="frame" style="display: block;">
<p>
<button style="width:70px" type="button">Add +</button>
</p>
<p>
<table class="table striped bordered hovered" >
<thead>
<tr>
<th class="text-left">Title</th>
<th class="text-left">Date</th>
<th class="text-left"> </th>
</tr>
</thead>
<tbody>
#foreach(var item in Model){
<tr class="">
<td>#item</td>
<td class="right"></td>
<td class="right" style="width: 180px; height: 35px"><button style="width:159px; height: 32px" type="button">Delete -</button></td>
</tr>
}
</tbody>
</table>
</p>
</div>
}
</div>
</div>
</div>
</div>
I need the foreach to refer to the Days in the Regions so that item would be one Day.
In your view you do a foreach within a foreach. In my example, it will creale a list of Days for all Regions... assuming the Day has a property "Name":
<ul>
#foreach( var r in Model){
foreach( var d in r.Days){
<li>d.Name</li>
}
}
</ul>

Categories