Trying to get the Selected checkbox values with the ID value - c#

Below is the Model
public class M_ProjectType
{
public Int16 ProjectTypeID { get; set; }
public String ProjectType { get; set; }
public Boolean IsActive { get; set; }
public Decimal Cost { get; set; }
public String Description { get; set; }
public Boolean IsChecked { get; set; }
}
Below is View Model
public class VM_Project
{
public string[] SkillID { get; set; }
public List<M_ProjectType> ProjectType { get; set; }
}
Below is Get Action method. here I am getting the data for projects that will be sent to View Model
[HttpGet, Route("Project")]
public async Task<ActionResult> Project()
{
var projectTypes = (await _projectTypes.ProjectTypesList()).Value;
var list = new List<M_ProjectType>();
foreach (var item in projectTypes)
{
list.Add(new M_ProjectType
{
Cost = item.Cost,
Description = item.Description,
IsActive = item.IsActive,
IsChecked = false,
ProjectType = item.ProjectType,
ProjectTypeID = item.ProjectTypeID
}
);
}
var project = new VM_Project
{
ProjectType = list
};
return View(project);
}
Below is Razor View
#foreach (var item in Model.ProjectType)
{
<table class="table table-striped">
<tbody>
<input type="hidden" value="#item.ProjectTypeID" name="ProjectTypeID" />
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => item.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => item.ProjectTypeID)
</td>
<td style="width:10%">#item.ProjectType</td>
<td style="width:80%">#item.Description</td>
<td style="width:5%"><b>$#item.Cost</b></td>
</tr>
</tbody>
</table>
}
Below is Post Action Method
[HttpPost, Route("Project")]
public ActionResult Project(VM_Project project)
{
return View();
}
Question: I am getting project.ProjectType = null. Any suggestion why
this is happening ?

I would recommend using EditorTemplates.
Create a folder named EditorTemplates in you Views/Shared direcotry.
Create a partial view based on your type i.e. M_ProjectType.cshtml
Put your markup that you use in foreach loop in M_ProjectType.cshtml file
#model M_ProjectType
<table class="table table-striped">
<tbody>
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => i.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => i.ProjectTypeID)
</td>
<td style="width:10%">#Model.ProjectType
#Html.HiddenFor(i=>i.ProjectType)
</td>
<td style="width:80%">#Model.Description</td>
<td style="width:5%"><b>$#Model.Cost</b></td>
</tr>
</tbody>
Then render your editor template in your form like (note: no foreach loop)
#Html.EditorFor(m=>m.ProjectType)
You should get correct model binded to your html elements back in controller.

Try this:
#foreach (var item in Model.ProjectType)
{
<table class="table table-striped">
<tbody>
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => item.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => item.ProjectTypeID, new { #Value = item.ProjectTypeID})
</td>
</tr>
</tbody>
</table>
}

Related

The model item passed into the ViewDataDictionary is of type Models but needs ViewModels

I've been struggling with this error for a few days now for an assignment and I can't get it fixed, I've shown it to another person and we are bewildered as to what could be the issue? "InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'FYP_RSVP_MGMT.Models.GuestList', but this ViewDataDictionary instance requires a model item of type 'FYP_RSVP_MGMT.ViewModels.GuestListViewModel'."
GuestListController:
public class GuestListController : Controller
{
public IActionResult Index()
{
GuestListViewModel guest = new GuestListViewModel();
return View("Index", guest);
}
public IActionResult CreateUpdate(GuestListViewModel guest)
{
if(ModelState.IsValid)
{
using (var db = DbHelpers.GetConnection()) {
if(guest.EditableGuest.GuestID == null)
{
/* Count the existing IDs and adds the next ID */
guest.EditableGuest.GuestID = guest.Guests.Count;
db.Insert<GuestList>(guest.EditableGuest);
}
/* If the guest already exists, we are updating the details*/
else
{
GuestList dbItem = db.Get<GuestList>(guest.EditableGuest.GuestID);
TryUpdateModelAsync<GuestList>(dbItem, "EditableGuest");
db.Update<GuestList>(dbItem);
}
}
return RedirectToAction("ViewGuestList");
}
else
{
return View("Index", new GuestList());
}
}
GuestListViewModel
public class GuestListViewModel
{
public GuestListViewModel()
{
using (var db = DbHelpers.GetConnection())
{
this.EditableGuest = new GuestList();
this.Guests = db.Query<GuestList>("Select * From GuestList").ToList();
}
}
public List <GuestList> Guests { get; set; }
/* Holds any instance of an object that is being added/edited/deleted etc */
public GuestList EditableGuest { get; set; }
}
GuestList Model
public class GuestList
{
public int? GuestID { get; set; }
[Required]
public string GuestName { get; set; }
[Required]
public string GuestType { get; set; }
[Required]
public string ContactDetails { get; set; }
public bool PlusOne { get; set; }
public string PlusOneName { get; set; }
[Required]
public string Response { get; set; }
}
Index.cshtml - where form is being displayed
#model FYP_RSVP_MGMT.ViewModels.GuestListViewModel
#{
ViewData["Title"] = "Guest RSVP";
}
#using (var form = Html.BeginForm("CreateUpdate", "GuestList", FormMethod.Post))
{
<div class="container" id="GuestRSVP">
<br/>
<br/>
<br/>
<h3> Welcome to [Bride] and [Groom]s Wedding</h3>
<h4>[Church Location]</h4>
<h4>[Wedding Date and Time]</h4>
<div class="container" id="RSVPTable" style="align-content:center">
<table>
<tr>
<td>Guest Name: </td>
<td>#Html.TextBoxFor(m => m.EditableGuest.GuestName)</td>
<td>#Html.HiddenFor(m => m.EditableGuest.GuestID)</td>
</tr>
<tr>
<td>Guest Type: </td>
<td>#Html.DropDownListFor(m => m.EditableGuest.GuestType, new List<SelectListItem> { new SelectListItem { Value = "Guest", Text = "Guest" }, new SelectListItem { Value = "Wedding Party", Text = "Wedding Party" } })</td>
</tr>
<tr>
<td>Contact Details: </td>
<td>#Html.TextBoxFor(m => m.EditableGuest.ContactDetails)</td>
</tr>
<tr>
<td>Plus One: </td>
<td>#Html.CheckBoxFor(m => m.EditableGuest.PlusOne)</td>
</tr>
<tr>
<td>Plus One Name: </td>
<td>#Html.TextBoxFor(m => m.EditableGuest.PlusOneName)</td>
</tr>
<tr>
<td>RSVP Response:</td>
<td>#Html.DropDownListFor(m => m.EditableGuest.Response, new List<SelectListItem> { new SelectListItem { Value = "Accept with Pleasure", Text = "Accept with Pleasure" }, new SelectListItem { Value = "Decline with Regret", Text = "Decline with Regret" } })</td>
</tr>
<tr>
<td><button class="btnSubmitRSVP" type="submit"> #(Model.EditableGuest.GuestID > 0? "Update": "Add") </button></td>
<td></td>
</tr>
</table>
</div>
</div>
}
We cannot figure out why the model is being passed and not the viewmodel? My code doesn't refer to the model? Any help would be much appreciated!
I'd say it's coming from here:
You're sending a GuestList in the else despite promising you'd send a GuestListViewModel at the top of the page:

How can I pass multiple values of a table/array to my controller

I create a table in my CSHTML, I want to pass the array of nr of items == aantal back to my controller however this doesn't seem to work. Any idea whats wrong or why I get a null reference in my controller?
CSHTML
#using (Html.BeginForm("OrderConfirm", "Beurs", new { vm = Model.Aantal }, method: FormMethod.Post))
{
<table class="table table-striped table-condensed table-bordered">
<tr>
<th>
Naam
</th>
<th>
Prijs
</th>
<th>
Minimum prijs
</th>
<th>
Factor
</th>
<th> Actie</th>
<!--
<th>Edit</th>-->
</tr>
#foreach (var item in Model.ItemLijstVm)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Naam)
</td>
<td>
€ #Html.DisplayFor(modelItem => item.Prijs)
</td>
<td>
€ #Html.DisplayFor(modelItem => item.MinimumPrijs)
</td>
<td>
#Html.DisplayFor(modelItem => item.Factor)
</td>
<td>
#Html.TextBoxFor(m => m.Aantal[item.Id - 1], new {type = "number" })
</td>
</tr>
}
</table>
<input type="submit" value=" Bevestig bestelling " width="120" />
}
ViewModel
public class BeursLijstViewModel
{
public IEnumerable<BeursItemViewModel> ItemLijstVm{get; set;}
public string Naam { get; set; }
public double Crash { get; set; }
//References naar animated gif
public bool Event { get; set; }
public string GifPath { get; set; }
public int[] Aantal { get; set; }
public int VerhoogAllePrijzen { get; set; }
public double Totaal { get; set; }
public SelectListItem Categorie { get; set; }
public BeursLijstViewModel(Beurs beurs)
{
ItemLijstVm= beurs.Items.Select(g => new BeursItemViewModel(g));
Naam = beurs.Naam;
Aantal = new int[beurs.Items.Count()];
Totaal = beurs.Totaal;
}
}
Controller
[HttpPost]
public ActionResult OrderConfirm(int[] vm) //VM is null but should be array
{
//Some more code
}
The reference I get on my post from my model is null, but if i declare it in my foreach loop like this, it works. I really don't have a clue what goes wrong:
#using (Html.BeginForm("Add", "Beurs", new { id = item.Id, aantal = Model.Aantal }, method: FormMethod.Post))
{
#Html.TextBoxFor(m => m.Aantal[item.Id - 1], new { type = "number" })
<input type="submit" value=" + " width="120"/>
}
I think you have to pass back the actual model not just array expecting to get result, since when it binds it goes several layers like name='Model.item[z]'
[HttpPost]
public ActionResult OrderConfirm(BeursLijstViewModel vm)
{
foreach (var item in vm.ItemLijstVm)
{
var response= vm.Aantal[item.Id - 1]
}
}
#using (Html.BeginForm("OrderConfirm", "Beurs", new { vm = Model.Aantal }, method: FormMethod.Post))
changing the above part in combination with the answer of #COLD TOLD to
#using (Html.BeginForm("OrderConfirm", "Beurs"))
fixed my problem. Thanks for the help!

C# , MVC , Instead table html

I have this model :
public class CoursesTeacher
{
public int Id { get; set; }
public string FullName { get; set; }
public IEnumerable<string> CourseName { get; set; }
public IEnumerable<int> CourseId { get; set; }
}
I would like to create an Instead table html by razor.
The teacher has a multiple courses.
like that
that
I wrote this code :
<table class="table table-bordered">
<tr>
<th>
#Html.ActionLink("Teacher Name", "RequestsTeachers")
</th>
<th>
#Html.ActionLink("Corese Name", "RequestsTeachers")
</th>
<th>
Edit
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td rowspan="#item.CourseName.Count()">
#Html.DisplayFor(modelItem => item.FullName)
</td>
#foreach (var courseName in item.CourseName)
{
<td>
#Html.DisplayFor(modelItem => courseName)
</td>
}
#foreach (var courseId in item.CourseId)
{
<td>
<div class="pull-right">
#Html.NoEncodeActionLink("<span class='glyphicon glyphicon-pencil'></span>", "Edit", "EditFinancial", "Control", routeValues: new { courseId = courseId }, htmlAttributes: new { data_modal = "", #class = "btn btn-default" })
</div>
</td>
}
</tr>
}
but created not correct :
correct
how to create correct ?
I'd go and create a viewmodel to represent the info for a course:
public class CourseInfoModel
{
public string CourseName { get; set; }
public int CourseId { get; set; }
public bool IsFirstCourse { get; set; }
}
Then in the model class, create a readonly property to get the data in a more suitable way:
public class CoursesTeacher
{
public int Id { get; set; }
public string FullName { get; set; }
public IEnumerable<string> CourseName { get; set; }
public IEnumerable<int> CourseId { get; set; }
public IList<CourseInfoModel> Courses
{
get
{
if (CourseName == null || CourseId == null || CourseId.Count() != CourseName.Count())
throw new Exception("Invalid data"); //courses and ids must have the same number of elements
var list = new List<CourseInfoModel>();
for (int i = 0; i < CourseName.Count(); i++)
{
list.Add(new CourseInfoModel
{
IsFirstCourse = i == 0,
CourseId = CourseId.ElementAt(i),
CourseName = CourseName.ElementAt(i),
});
}
return list;
}
}
}
Now in the view is easy to render the table the way you want:
#model IEnumerable<MvcTable.Models.CoursesTeacher>
<table class="table table-bordered">
<tr>
<th>
#Html.ActionLink("Teacher Name", "RequestsTeachers")
</th>
<th>
#Html.ActionLink("Course Name", "RequestsTeachers")
</th>
<th>
Edit
</th>
</tr>
#foreach (var item in Model)
{
foreach (var courseItem in item.Courses)
{
<tr>
#if (courseItem.IsFirstCourse)
{
<td rowspan="#item.Courses.Count">
#Html.DisplayFor(modelItem => item.FullName)
</td>
}
<td>
#Html.DisplayFor(modelItem => courseItem.CourseName)
</td>
<td>
<div class="pull-right">
<span class='glyphicon glyphicon-pencil'></span>
</div>
</td>
</tr>
}
}
</table>
Instead of keeping the CourseName and CourseIds to seperate lists. Why not create a class to represent a course and use that ?
public class CourseVm
{
public int Id { set; get;}
public string Name { set; get;}
}
public class CoursesTeacher
{
public int Id { set;get;}
public string FullName { set;get;}
public List<CourseVm> Courses { set;get;}
}
and in the view which is strongly typed to a collection CoursesTeacher
#model IEnumerable<CoursesTeacher>`
<table>
#foreach(var t in Model)
{
<tr>
<td>#t.FullName</td>
<td>
<table>
#foreach(var c in t.Courses)
{
<tr><td>#c.Name</td>
<td><button>Some button</button></td>
</tr>
}
</table>
</td>
</tr>
}
</table>

Not able to see ViewModel property in View?

I'm still trying to get my head wrapped around using ViewModels and IEnumerable/List as properties. I'm obviously missing something that is not allowing me to see my IEnumerable in my View.
What I'm ultimately trying to do is have a view that will show a list of unassigned users not assigned to a Group (called Patrols in this case and would have PatrolId=0). The table will have a checkbox next to each member. Above that table will be a DropDownList of the available Patrols. The Admin will come to the page to see those that aren't assigned, select a Patrol from the DDL at the top, check the users he want's to assign to that Patrol, and then submit the form that will pass the PatrolID from the DDL and find all the selected members in order to update their record with that PatrolId.
In the View below when I go to loop through the Scout property, I would assume I would be able to use Model.Scout in this part in order to loop through and write out all the members in that IEnumerable.
#for (var i = 0; i < Model.Count(); i++)
However, when I try to use intellisense to see the Scout property when using the Model, I don't see the property. In addition to that I would think I would need to first check the Scout property to see if there is a count before I write out all the rows. Again, I can't see the Scout property in order to check it's count.
ViewModel
public class PatrolMemberViewModel
{
[Key]
public int MemberId { get; set; }
public int PatrolId { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Phone")]
public string PhonePrimary { get; set; }
[Display(Name = "Email")]
public string EmailPrimary { get; set; }
public bool IsSelected { get; set; }
}
public class PatrolUnassignedViewModel
{
public SelectList Patrols { get; set; }
public IEnumerable<PatrolMemberViewModel> Scout { get; set; }
}
Controller
// GET:
public ViewResult Unassigned()
{
PatrolUnassignedViewModel unassinged = new PatrolUnassignedViewModel();
unassinged.Patrols = new SelectList(repository.SelectAllPatrols());
unassinged.Scout = repository.SelectAllUnassigned();
return View(unassinged);
}
Repository
public IEnumerable<PatrolMemberViewModel> SelectAllUnassigned()
{
using (DataContext db = new DataContext())
{
var results = (from p in db.Person
where p.IsActive == true
&& p.IsScout == true
&& p.PatrolId == 0
select new PatrolMemberViewModel
{
MemberId = p.PID,
FirstName = p.FirstName ?? string.Empty,
LastName = p.LastName ?? string.Empty,
EmailPrimary = p.EmailPrimary ?? string.Empty,
PhonePrimary = p.PhonePrimary ?? string.Empty,
PatrolId = p.PatrolId,
IsSelected = false
}
).OrderBy(o => o.LastName).ThenBy(o => o.FirstName).ToList();
return results;
}
}
public IEnumerable<PatrolName> SelectAllPatrols()
{
return db.PatrolNames;
}
View
#model IList<ProjectName.ViewModels.PatrolUnassignedViewModel>
#{
ViewBag.Title = "Unassigned";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Patrols</h2>
<h4>Assign Scouts to a Patrol.</h4>
#using (Html.BeginForm("Update", "Patrol", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(false, "", new { #class = "alert alert-danger" })
<table class="table table-bordered table-striped table-hover table-condensed tbackground">
<tr>
<th class="text-center">
</th>
<th class="text-center">
First Name
</th>
<th class="text-center">
Last Name
</th>
<th class="text-center">
Email
</th>
<th class="text-center">
Phone
</th>
</tr>
#for (var i = 0; i < Model.Count(); i++)
{
<tr>
<td class="text-center">
#Html.CheckBoxFor(m => m[i].IsSelected)
</td>
<td>
#Html.DisplayFor(m => m[i].FirstName)
</td>
<td>
#Html.DisplayFor(m => m[i].LastName)
</td>
<td>
#Model[i].EmailPrimary
</td>
<td class="text-center">
#Html.DisplayFor(m => m[i].PhonePrimary)
</td>
</tr>
}
</table>
<div class="control-wrapper">
<input type="submit" id="btnSubmit" value="Assign Scouts" class="btn btn-success" />
</div>
}
<p> </p>
You controller is returning a single instance of class PatrolUnassignedViewModel
public ViewResult Unassigned()
{
PatrolUnassignedViewModel unassinged = new PatrolUnassignedViewModel();
unassinged.Patrols = new SelectList(repository.SelectAllPatrols());
unassinged.Scout = repository.SelectAllUnassigned();
return View(unassinged);
}
Your view is expecting an IList
#model IList<ProjectName.ViewModels.PatrolUnassignedViewModel>
When it should be expecting
#model ProjectName.ViewModels.PatrolUnassignedViewModel
Your scout is an IEnumerable so doesn't have a count method so should be
public IList<PatrolMemberViewModel> Scout { get; set; }
public IList<PatrolMemberViewModel> SelectAllUnassigned()
{
}
You should be doing your loop like this
#for (var i = 0; i < Model.Scout.Count(); i++)
{
<tr>
<td class="text-center">
#Html.CheckBoxFor(m => m.Scout[i].IsSelected)
</td>
<td>
#Html.DisplayFor(m => m.Scout[i].FirstName)
</td>
<td>
#Html.DisplayFor(m => m.Scout[i].LastName)
</td>
<td>
#Model.Scout[i].EmailPrimary
</td>
<td class="text-center">
#Html.DisplayFor(m => m.Scout[i].PhonePrimary)
</td>
</tr>
}
Am I missing something here?
From your GET action method, you are passing a single object of PatrolUnassignedViewModel. But your view is bound to a collection of PatrolUnassignedViewModel. So change your view to be like
#model PatrolUnassignedViewModel
Now you can use the Model.Scout property which is a collection.
#model PatrolUnassignedViewModel
<h2>Total : #Model.Scout.Count()</h2>
#foreach(var item in Model.Scout)
{
<label>#item.FirstName</label>
}

Trouble passing data from database table to view

I am filling an SQL table with a query and then trying to pass the data from the model (for the table) into the view. I am attempting to use a ViewModel to pass the data to the view in a Controller Action.
Here is the Model:
public partial class Report
{
public int Id { get; set; }
public string Number { get; set; }
public Nullable<decimal> Amount { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> ReasonId { get; set; }
public string Notes { get; set; }
}
IEnumerable ViewModel:
public class ReportViewModel
{
public IEnumerable<Report> Reports { get; set; }
}
Controller Action:
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
//Unrelated Code to read a CSV into another database table goes here
//But was removed so it wouldn't be confusing.
var db = new Report();
var reportModel = new ReportViewModel()
{
Reports = new List<Report>() {new Report()}
};
return View("Upload", reportModel);
}
View:
#model Entities.Models.ReportViewModel
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Number</th>
<th>Amount</th>
<th>Date</th>
<th>Reason Id</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var item in Model.Reports.Where(x => x.Id != null))
{
<tr>
<td>
#item.Id
</td>
<td>
#item.Number
</td>
<td>
#item.Amount
</td>
<td>
#item.Date
</td>
<td>
#item.ReasonId
</td>
<td>
#item.Notes
</td>
</tr>
}
}
</tbody>
</table>
But I get an exception when I try to return the View which says ReportViewModel is not assignable to model type IEnumerable ReportViewModel
So I am just trying to pass all the rows from the Report database to an HTML table in my view. Any help, or a better way to do this would be appreciated.

Categories

Resources