Get value in View from ICollection to pass an ActionLink parameter - asp.net

Hellow!, i'm need to be able to get the Id from Compromisos in a View of Gestion. My needs is to get the Id to passess to an ActionLink and go to the View Details of Compromisos
public class Gestion
{
//abbreviated to not make the long post
public Personales Personales { get; set; }
public ICollection<Compromisos> Compromisos { get; set; }
}
and
public class Compromisos
{
//abbreviated to not make the long post
public Personales Personales { get; set; }
public Gestion Gestion { get; set; }
}
Actually i get the Id using this
#foreach (var item in Model.Gestion)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Compromisos)
</td>
</tr>
}
but i want to be able to do this: #Html.ActionLink("Detalle", "Details", "Compromisos", new { id = item.Compromisos}) but doesn't work.
Any suggestions?

Should you be iterating the Model.Compromisos model instead of Model.Gestion? Maybe post your whole model.
#foreach (var item in Model.Compromisos)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Gestion.[Property])
</td>
<td>
#Html.ActionLink("Detalle", "Details", "Compromisos", new { id = item.Compromisos.Id})
</td>
</tr>
}

#Waragi I finally did it.
#foreach (var Item in Model.Compromisos)
{
#if (item.Id == Item.GestionId)
{
<a asp-action="Details" asp-controller="Compromisos" target="_blank" asp-route-id="#Item.Id">Detalle</a>
}
}
In the controller I added .Include(c => c.Compromisos)
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var gestion = await _context.Gestion
.Include(c => c.Compromisos) //before I had included .ThenInclude(c => c.Compromisos)
.SingleOrDefaultAsync(m => m.Id == id);
if (gestion == null)
{
return NotFound();
}
return View(gestion);
}

Related

How to take value from Select/Option and inserted into href

I need help if it is possible. I have a list of classrooms, as it is in the picture below. I want to list all teachers in the "select option" and when the user selects the teacher he can click save and the classroom will be updated, as it is in the href. How can I take the value after the foreach loop?
<select id="teachers">
#foreach(var teacher in #Model.Teachers){
<option value="#teacher.Id">#teacher.Id</option>
}
</select>
<a asp-controller="Classroom" asp-action="Update" asp-route-teacherId=""></a>
<a asp-controller="Classroom" asp-action="Update" asp-route-teacherId="XX">Save</a>
First, for the above a tag helper, the generated HTML like this:
Save
or
Save
Besides, to update teachers in specific classrooms, you should also submit the classroom id to the Update action method, so, the generated URL should have multiple parameters(teacherid and classroomId), like this: Save
More detail information, see Anchor Tag Helper.
I have a list of classrooms, as it is in the picture below. I want to
list all teachers in the "select option" and when the user selects the
teacher he can click save and the classroom will be updated, as it is
in the href. How can I take the value after the foreach loop?
From your description, each classroom (row) should have a <select> element to choose the teacher and a "Save" button to update the current row update, right?
In this scenario, you could use the select element's change event to get the selected value, and then update the <a> tag href attribute.
You can refer the following sample:
Model:
public class ClassRoom
{
public int ID { get; set; }
public string Classroom { get; set; }
public string SubJect { get; set; }
public string Teacher { get; set; }
public DateTime Date { get; set; }
}
public class Teacher
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Subject
{
public int Id { get; set; }
public string SubjectName { get; set; }
}
public class ClassRoomViewModel
{
public List<ClassRoom> ClassRooms { get; set; }
public List<Teacher> Teachers { get; set; }
public List<Subject> Subjects { get; set; }
}
Controller:
public class ClassRoomController : Controller
{
public IActionResult Index()
{
// you could query the database to get the data. The following is the test data.
var viewmodel = new ClassRoomViewModel();
viewmodel.ClassRooms = new List<ClassRoom>()
{
new ClassRoom(){ ID=1, Classroom="EOIS1", Date=DateTime.Now },
new ClassRoom(){ ID=2, Classroom="EOIS2", Date=DateTime.Now }
};
viewmodel.Teachers = new List<Teacher>()
{
new Teacher(){ Id=101, Name="Tom"},
new Teacher(){ Id=102, Name="Jack"}
};
return View(viewmodel);
}
public IActionResult Update(int teacherId, int classroomid)
{
//update the classroom
//redirect to the Index page and refresh the page.
return RedirectToAction(nameof(Index));
}
}
View Page:
#model MVCWebApplication.Models.ClassRoomViewModel
<table class="table" id="customers" >
<thead>
...
</thead>
<tbody>
#foreach (var item in Model.ClassRooms) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Classroom)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubJect)
</td>
<td>
<select id="teachers" class="teachers">
<option value="0">select teacher</option>
#foreach (var teacher in #Model.Teachers)
{
<option value="#teacher.Id">#teacher.Name</option>
}
</select>
</td>
<td>
<a asp-controller="ClassRoom" asp-action="Update" asp-route-classroomid="#item.ID" asp-route-teacherId="">Save</a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
</tr>
}
</tbody>
</table>
#section Scripts{
<script>
$(function () {
$(".teachers").each(function (Index, item) {
$(item).change(function () {
var teacherid = $(this).val(); //get the selected value.
var existinghref = $(item).parent().parent().find("a").attr("href"); //get the hyperlink href attribute.
if (teacherid != 0) {
existinghref = existinghref + "&teacherId=" + teacherid; //add the parameter at the end of the request url.
$(item).parent().parent().find("a").attr("href", existinghref); //update the hyperlink href attribute.
}
else {
alert("Please select teacher"); //show prompt to let user select teacher.
}
});
});
});
</script>
}
The result as below:

Using checkboxes to filter table by boolean columns in MVC 5

I want to be able to filter the contents of my "Contacts" table by interests, and I am currently attempting to accomplish this through a series of Boolean properties representing each individual interest. The plan was that I was going to have a series of checkboxes on the Index page for each Interest that would allow the user to display only Contacts that had one or more of the appropriate Interest variables set to "true" for each checkbox that was checked (or all Contacts if no checkboxes were selected). As far as I can tell this is theoretically possible, but my research so far has not turned up any results as to how to perform this sort of filtering in this specific manner. Could anyone here perhaps point me in the right direction?
EDIT: Here is what code I have so far related to the problem:
EDIT2: I have a nominally working set of checkboxes in place, but now the filtering isn't working quite the way I want it to. I want the controller to send the view only whichever Contacts have one or more of the same variables set to "true" as the appropriate checked boxes, or all Contacts if no boxes are checked. What I have now works fine for single selections, but with multiple selections only returns entries that match all checked boxes. I would like to know how to conditionally filter more effectively and efficiently than what I have now.
Here is my model- the "Interests" string was just to make it more presentable in the Index than just a line of grayed-out checkboxes:
public class Contact : IValidatableObject
{
public int Id { get; set; }
public string Email { get; set; }
public string PhoneNum { get; set; }
public string Name { get; set; }
public bool LikesClassic { get; set; }
public bool LikesCountry { get; set; }
public bool LikesHipHop { get; set; }
public bool LikesMetal { get; set; }
public bool LikesPop { get; set; }
public bool LikesRap { get; set; }
public bool LikesRock { get; set; }
public string Interests
{
get
{
var interests = "";
if (this.LikesClassic)
interests = interests + "[Classic] ";
if (this.LikesCountry)
interests = interests + "[Country] ";
if (this.LikesHipHop)
interests = interests + "[Hip-Hop] ";
if (this.LikesMetal)
interests = interests + "[Metal] ";
if (this.LikesPop)
interests = interests + "[Pop] ";
if (this.LikesRap)
interests = interests + "[Rap] ";
if (this.LikesClassic)
interests = interests + "[Rock] ";
return interests;
}
}
Here is my View- the checkboxes are in place but not yet functional
#model IEnumerable<ContactInterests.Models.Contact>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm())
{
<p>
Classic: #Html.CheckBox("Classic")
Country: #Html.CheckBox("Country")
Hip-Hop: #Html.CheckBox("HipHop")
Metal: #Html.CheckBox("Metal")
Pop: #Html.CheckBox("Pop")
Rap: #Html.CheckBox("Rap")
Rock: #Html.CheckBox("Rock")
<input type="submit" value="Search" />
</p>
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.PhoneNum)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
Interests
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.PhoneNum)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Interests)
</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>
}
</table>
Here is my Index ActionResult for my Contacts controller; again, it is crude but nominally functional, just not in the way I would have preferred:
public ActionResult Index(string Classic, string Country, string HipHop,
string Metal, string Pop, string Rap, string Rock)
{
var contactList = from c in db.Contacts select c;
if (Classic == "true")
{
contactList = contactList.Where(c => c.LikesClassic == true);
}
if (Country == "true")
{
contactList = contactList.Where(c => c.LikesCountry == true);
}
if (HipHop == "true")
{
contactList = contactList.Where(c => c.LikesHipHop == true);
}
if (Metal == "true")
{
contactList = contactList.Where(c => c.LikesMetal == true);
}
if (Pop == "true")
{
contactList = contactList.Where(c => c.LikesPop == true);
}
if (Rap == "true")
{
contactList = contactList.Where(c => c.LikesRap == true);
}
if (Rock == "true")
{
contactList = contactList.Where(c => c.LikesRock == true);
}
if (Classic == "false" && Country == "false" && HipHop == "false" && Metal == "false" && Pop == "false" && Rap == "false" && Rock == "false")
{
contactList = from c in db.Contacts select c;
}
return View(contactList.ToList());
}

List of Items always null MVC 5

I am stuck in this problem and i cannot solve it.
This is my ViewModel
public class AddOrderReceive
{
public string item_name { get; set; }
public DateTime? date_received { get; set; }
public decimal? quantity_received { get; set; }
public bool IsSelected { get; set; }
public decimal? item_rate { get; set; }
}
This is my View
#model List<newtest.Models.AddOrderReceive>
#if(Model != null && Model.Count > 0)
{
for(var i = 0; i < Model.Count; i++)
{
<tr>
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
else
{
#Html.HiddenFor(r => Model[i].item_id)
<td>#Html.CheckBoxFor(r => Model[i].IsSelected)</td>
<td>#Html.EditorFor(r => Model[i].item_rate)</td>
}
</tr>
}
}
And finally, This is my Controller:
[HttpGet]
public ActionResult AddRAR(int? my_id)
{
try
{
var get_items = (from or in db.orders
where or.id == my_id
select new AddOrderReceive()
{
item_name = or.item_name,
quantity_received = or.quantity_receive,
date_received = or.date_receive,
order_receive_id = or.order_receive_id
}).ToList();
foreach(var t in get_items)
{
var get_remain = (from ra in db.order_detail
where ra.contract_id == t.ca_id && ra.order_receive_id == t.order_receive_id
select new
{
consump_quantity = ra.consump_quantity
});
t.quantity_remaining = t.quantity_received - get_remain.Sum(r => r.consump_quantity) ?? t.quantity_received;
}
return View(get_items);
}
catch(Exception ex)
{
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddReceivng(List<AddOrderReceive> rc_form)
{
//Some Logic
}
The problem is that whenever I post the form, it is always null. But when I remove this block:
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
It starts working. I don't know what's the problem. I've searched everywhere but still can't figure out the problem here.
Your #if(Model[i].quantity_remaining == 0) block of code, if its executed in the first iteration, means that your collection indexers would not be zero based. The DefaultModelBinder requires that collection indexers start at zero and be consecutive.
You can override this behavior by including a hidden input for the indexer. Note also that an <input> is not a valid child of a <tr>, and should be inside a <td> element.
for(var i = 0; i < Model.Count; i++)
{
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
else
{
<td>
<input type="hidden" name="Index" value="#i" /> // Add this
#Html.HiddenFor(r => r[i].item_id)
#Html.CheckBoxFor(r => r[i].IsSelected)
</td>
<td>#Html.EditorFor(r => r[i].item_rate)</td>
}
}

My form ignores Required attributes from model

I'm having troubles with my form validation. For some reason the form ignores any [Required] attribute I have in my model.
Model: (Stripped down for easy read)
public class NotEmployeesModel
{
public NotEmployeesModel()
{
DetailModel = new NotEmployeesDetailModel();
}
public NotEmployeesDetailModel DetailModel { get; set; }
}
public class NotEmployeesDetailModel
{
public NotEmployeesDetailModel()
{
}
public NotEmployeesDocumentModel DocumentModel { get; set; }
}
public class NotEmployeesDocumentModel
{
public NotEmployeesDocumentModel()
{
}
public NotEmployeeDocumentInputModel DocumentInput { get; set; }
public class NotEmployeeDocumentInputModel
{
public NotEmployeeDocumentInputModel()
{
}
public NotEmployeeDocumentInputModel(int notEmployeeId)
{
NotEmployeeId = notEmployeeId;
}
public int NotEmployeeId { get; set; }
public int SelectedDocumentType { get; set; }
[Required(ErrorMessageResourceType = typeof(ErrorMessages), ErrorMessageResourceName = "Star")]
public string Description { get; set; }
[Required(ErrorMessageResourceType = typeof(ErrorMessages), ErrorMessageResourceName = "Star")]
public HttpPostedFileBase File { get; set; }
}
}
For each view or partial I have a separate model class.
Form:
#model NotEmployeesDocumentModel
#using (Html.BeginForm("AddNotEmployeeDocument", "Home", FormMethod.Post, new { id = "form-add-document", enctype = "multipart/form-data" }))
{
#Html.HiddenFor(x => x.DocumentInput.NotEmployeeId)
<table class="table-output">
<thead>
<tr>
<td>#Html.Label("Sort", Labels.Sort)</td>
<td>#Html.Label("Description", Labels.Description)</td>
<td>#Html.Label("Type", Labels.Type)</td>
<td class="text-align-right"></td>
</tr>
</thead>
<tbody>
<tr>
<td>
<i class="fa fa-plus-square cursor-pointer add-document"></i>
<input type="file" id="DocumentInput_File" name="DocumentInput.File" required="required" />
#Html.ValidationMessageFor(x => x.DocumentInput.File)
</td>
<td>
#Html.TextBoxFor(x => x.DocumentInput.Description, new { #class = "width300px hardware-setup-input", placeholder = "Vul hier een omschrijving in..." })
#Html.ValidationMessageFor(x => x.DocumentInput.Description)
</td>
<td>
#Html.DropDownListFor(x => x.DocumentInput.SelectedDocumentType, Model.DocumentTypes, "--- Maak een keuze ---")
</td>
<td class="text-align-right">
<span id="btn-add-document" class="button-org">#Labels.Save</span>
</td>
</tr>
</tbody>
</table>
}
Structure of my page: View / Partial / Partial (Here is my form)
JS:
$("#btn-add-document").on("click", function () {
var frm = $("#form-add-document");
if (frm.valid()) {
frm.ajaxSubmit({
dataType: "html",
success: function (responseText) {
$("#document-container").html(responseText);
$("#DocumentInput_Description").text("");
$("#DocumentInput_SelectedDocumentType").val("");
loadDocumentPartial();
}
});
}
});
I'm using jQuery Form plugin from malsup to submit my form through ajax.
Controller:
[HttpPost]
public ActionResult AddNotEmployeeDocument(NotEmployeesDocumentModel input)
{
// do some code
}
As you can see in the parameters of my ActionResult I can't put NotEmployeesDocumentInputModel like I always do but I'm forced to use the parent class.
I have no idea what I'm doing wrong. This is the first time I encounter such problem.

Radio button list using editor templates for merging contacts

I am trying to display a form for merging two contacts in ASP.net MVC 5.
The form should look like this where each row holds a radio button group consisting of 2 options:
The form shows up just fine, and the radio groups work (I can select each group). However, when the model is posted back to the server, the Values list is empty (not preserved). I would like to get both the selected id but of course also the actual text value back in the controller. I prefer to do this using Editor Templates and if possible without for loops.
The current results (Values = null):
EDIT to respond to comments: I would prefer not to re-fetch the values in the controller again, because it results in a call to a web service. I have tried some variants of HiddenFor without results.
My models look like this:
public class Contact
{
public List<ContactRow> Rows { get; set; }
public Contact()
{
this.Rows = new List<ContactRow>();
this.Rows.Add(new ContactRow("First Name", "Homer", "Homie"));
this.Rows.Add(new ContactRow("Last Name", "Simpson", "Simson"));
this.Rows.Add(new ContactRow("Email", "mail1", "mail2"));
this.Rows.Add(new ContactRow("Company Phone", "Phone1", "Phone2"));
this.Rows.Add(new ContactRow("Mobile Phone", "Mobile1", "Mobile2"));
}
}
public class ContactRow
{
public int Selection { get; set; }
public string Label { get; set; }
public List<ValueSet> Values { get; set; }
public ContactRow(string Label, string LeftValue, string RightValue, int Selection = 0)
{
if (LeftValue== null) LeftValue= "";
if (RightValue== null) RightValue= "";
this.Label = Label;
this.Selection = Selection;
this.Values = new List<ValueSet>(2);
this.Values.Add(new ValueSet() { ID = 0, ValueText = LeftValue});
this.Values.Add(new ValueSet() { ID = 1, ValueText = RightValue});
}
public ContactRow() { }
}
public class ValueSet
{
public int ID { set; get; }
public string ValueText { set; get; }
}
The Controller:
public ActionResult Index()
{
Contact model = new Contact();
return View(model);
}
public ActionResult MergeContacts(Contact model)
{
return RedirectToAction("Index");
}
And the views:
Index.cshtml
#model RadioTest.Models.Contact
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("MergeContacts", "Home", FormMethod.Post, new { encType = "multipart/form-data", id = "contactDetailsForm", name = "contactDetailsForm" }))
{
<div>
<table class="table" width="100%">
<tr>
<th style="text-align:left">Label</th>
#*<th style="text-align:right">R1</th>*#
<th style="text-align:left">
Left Value
</th>
#*<th style="text-align:right">R2</th>*#
<th style="text-align:left">
Right Value
</th>
</tr>
#Html.EditorFor(model => model.Rows)
</table>
<input type="submit" />
</div>
}
Editor Template for ContactRow:
ContactRow.cshtml
#model RadioTest.Models.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#foreach (var v in Model.Values)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, v.ID) #v.ValueText
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)
Just change your foreach to for:
#model MVCApp.Controllers.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#for (int i = 0; i < Model.Values.Count; i++)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, Model.Values[i].ID) #Model.Values[i].ValueText
#Html.HiddenFor(model => Model.Values[i].ID)
#Html.HiddenFor(model => Model.Values[i].ValueText)
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)

Resources