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.
Related
I have a form with list of records, and there are 2 check box
To skip record from sending
To further work with that record.
I want to send this checkbox value to 2 different method in my mvc controller
SkipRecord()
2)SendTodb()
Issues here is my view code
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<form id="form" method="post">
<div class="container" id="heading">
<div class="col-xs-6 col-md-6 col-lg-6">
<h2 class="h2Heading">List</h2>
</div>
</div>
<h2></h2>
<div class="container" id="list">
<div class="row">
<div class="col-lg-12">
<div class="main clearfix">
<table class="table table-hover table-responsive " id="waitingList">
<thead>
<tr>
<th>Name</th>
<th>Last Updated</th>
<th>DID</th>
<th>OtherId</th>
<th>Status</th>
<th>Remove</th>
<th>Update</th>
</tr>
</thead>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastUpdatedTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.DID)
</td>
<td>
#Html.DisplayFor(modelItem => item.OtherId)
</td>
<td class="text-center">
<span class="label-status label-default">
New
</span>
</td>
#using (Html.BeginForm(new { action = "SkipRecord" }))
{
<td>
#Html.HiddenFor(modelItem => item.ID)
<input id="checkbox" name="skipRecords" value="#item.ID" type="checkbox" />
</td>
}
</tr>
}
</table>
<div class="col-md-offset-2">
<button type="submit" class="btn btn-danger btn-md pull-left loginbtn">Update</button>
</div>
</div>
</div>
</div>
</div>
</form>
</body>
</html>
I want to try and not use ViewModel
I want to pass checkedvalue and Unchecked value with the record id.
because there are 2 different methods if use #using(Html.BeginForm) and pass the method it will only take one method but i want to send data to 2 different methods. please if anyone can help?
Just call the second method from the first. You could create a new method called ProcessChecks or something like that that uses logic to determine which method to send the data to.
What Mark said in the comments is also true; you can't have one form element inside another.
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!
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.
I am using .Net MVC5 and I am trying to create an Index view with an Edit Link(or button) that will POST(so I can't use ActionLink) an entire Model item Entity from the list of entities presented in the View. How do I do it?
my code(so far) is below
#model IEnumerable<Projname.Models.MyEntity>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>Hello there</th>
<th>life is good</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#using (Html.BeginForm("Edit", "Edit", FormMethod.Post))
{
#Html.Hidden(mytem => item);
<input type="submit" value="Edit" class="btn btn-default" />
}
</td>
<td>
#Html.ActionLink("Details", "Details", new { id = item.PrimeKey }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PrimeKey })
</td>
</tr>
}
</table>
</body>
</html>
I am assuming that there is a better way to do it instead of creating a hidden field for each of the properties of the entity.
You need to put the items you want to edit or change into a form
<form class="form-horizontal" action="GetItemsFromView" method="post">
<input type="text" name="EditedModelItem">
</form>
Afterwards you can call any edited item in your controller, through
string hold = Request.Form["EditedModelItem"];
in the GetItemsFromView method.
Wrap everything in:
#using (Html.BeginForm("Edit", "Edit", FormMethod.Post))
{
}
Then:
public ActionResult Edit(Model model)
{
if (ModelState.IsValid)
{
}
}
Or:
public ActionResult Edit(FormCollection formCollection)
{
}
This question already has answers here:
Multiple checkboxes in razor (using foreach)
(3 answers)
Closed 7 years ago.
I would like to edit a list of items and save them all together in the same submit. Is it possible? If so, how?
I have the following piece of code, but it does not give the wanted result. Or otherwise I don't know what to write for the counterpart in the controller.
#using (Html.BeginForm("Save", "MyController", FormMethod.Post))
{
<fieldset>
<table class="table table-striped table-hover ">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Datum</th>
<th>NewValue</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.Id)
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Value)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Value)
</td>
</tr>
}
</tbody>
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Update Thanks to #Jonesopolis I came up with this working solution
#using (Html.BeginForm("Save", "MyController", FormMethod.Post))
{
<fieldset>
<table class="table table-striped table-hover ">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Datum</th>
<th>NewValue</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.HiddenFor(modelItem => modelItem[i].Id)
#Html.DisplayFor(modelItem => modelItem[i].Name)
</td>
<td>
#Html.DisplayFor(modelItem => modelItem[i].Value)
</td>
<td>
#Html.TextBoxFor(modelItem => modelItem[i].Value)
</td>
</tr>
}
</tbody>
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
For MyController
public class MyController : Controller
{
[HttpPost]
public ActionResult Save(IEnumerable<NameDoesNotMatter> newValues)
{
...
}
}
public class NameDoesNotMatter
{
public int Id { get; set; }
public decimal? Value { get; set; }
}
Now see if i can work out the thing with the templates. The link of #StephenMuecke should be sufficient
Update 2
Well that's wasn't that hard the code is now
#using (Html.BeginForm("Save", "MyController", FormMethod.Post))
{
<fieldset>
<table class="table table-striped table-hover ">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
<th>Datum</th>
<th>NewValue</th>
</tr>
</thead>
<tbody>
#Html.EditorForModel()
</tbody>
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
And for Views/Shared/EditorTemplates/TypeOfModel.cshtml
#model TypeOfModel
<tr>
<td>
#Html.HiddenFor(item => item.Id)
#Html.DisplayFor(item => item.Name)
</td>
<td>
#Html.DisplayFor(item => item.Value)
</td>
<td>
#Html.TextBoxFor(item => item.Value)
</td>
</tr>
The controller remains the same
When you just show items using a for loop then the naming convention used in the resulting html tag doesn't match up with what MVC is expecting when it binds the model upon form submit. The easiest way to fix this is to use #Html.EditorFor and custom editor templates. Here are a couple of examples:
ASP.NET MVC DisplayTemplate and EditorTemplates for Entity Framework DbGeography Spatial Types
Extending Editor Templates for ASP.NET MVC