I'm really hoping that you can help me out with this question. I've trawled the site and found things that do part of what I want but I can't quite get all the pieces together. I'm trying to build a screen in ASP.Net Mvc 4 that allows a user to create a record (of a training course) and associate many employee records to it.
Basically I've build a controller over the intersection table between courses and employees and a view to allow the selection of the course (and to fill in some meta data) and then use a kendo mutliselect control to pick employees. I store the emloyee Id's in an array and can post it back to the action on the controller but I'm not sure how to pass the model containing the course. My intention was to pass the course model with the array and then loop through the array and create a course for each employee.
any help you can offer would be great, thanks!
My model looks like this:
namespace TrainingKendoUI.Models
{
using System;
using System.Collections.Generic;
public partial class TRAINING_EMPLOYEE_COURSES
{
public int EMP_COURSE_ID { get; set; }
public int EMPLOYEE_ID { get; set; }
public int COURSE_ID { get; set; }
public Nullable<System.DateTime> DATE_ATTENDED { get; set; }
public Nullable<decimal> COURSE_COST { get; set; }
public string COURSE_RESITS { get; set; }
public Nullable<int> PROVIDER_ID { get; set; }
public Nullable<int> EMP_COURSE_STATUS_ID { get; set; }
public Nullable<int> VENUE_ID { get; set; }
public virtual TRAINING_COURSES TRAINING_COURSES { get; set; }
public virtual TRAINING_EMPLOYEE_COURSE_STATUS TRAINING_EMPLOYEE_COURSE_STATUS { get; set; }
public virtual TRAINING_EMPLOYEES TRAINING_EMPLOYEES { get; set; }
public virtual TRAINING_PROVIDERS TRAINING_PROVIDERS { get; set; }
public virtual TRAINING_VENUES TRAINING_VENUES { get; set; }
}
}
and my action method like this:
[HttpPost]
public ActionResult MultiCreate(TRAINING_EMPLOYEE_COURSES training_employee_courses, int courseId, int[] empId)
{
empId.ToString(); //Used as a break point to see what's been passed in
//The intention is to add some processing to handle the multiple creations...
if (ModelState.IsValid)
{
db.TRAINING_EMPLOYEE_COURSES.Add(training_employee_courses);
db.SaveChanges();
return RedirectToAction("List");
}
ViewBag.COURSE_ID = new SelectList(db.TRAINING_COURSES, "COURSE_ID", "COURSE_NAME", training_employee_courses.COURSE_ID);
ViewBag.EMP_COURSE_STATUS_ID = new SelectList(db.TRAINING_EMPLOYEE_COURSE_STATUS, "EMP_COURSE_STATUS_ID", "EMP_COURSE_STATUS", training_employee_courses.EMP_COURSE_STATUS_ID);
ViewBag.EMPLOYEE_ID = new SelectList(db.TRAINING_EMPLOYEES, "EMPLOYEE_ID", "FIRST_NAME", training_employee_courses.EMPLOYEE_ID);
ViewBag.PROVIDER_ID = new SelectList(db.TRAINING_PROVIDERS, "PROVIDER_ID", "PROVIDER_NAME", training_employee_courses.PROVIDER_ID);
ViewBag.VENUE_ID = new SelectList(db.TRAINING_VENUES, "VENUE_ID", "VENUE_NAME", training_employee_courses.VENUE_ID);
return View(training_employee_courses);
}
and the view like this:
@model TrainingKendoUI.Models.TRAINING_EMPLOYEE_COURSES
@{
ViewBag.Title = "Add Employees to a Course";
}
<h2>Select Course</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>TRAINING_EMPLOYEE_COURSES</legend>
<table>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.COURSE_ID, "Course")
</div>
<div class="editor-field">
@Html.DropDownList("COURSE_ID", String.Empty)
@Html.ValidationMessageFor(model => model.COURSE_ID)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.DATE_ATTENDED)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DATE_ATTENDED, new { @class="FormTextBox" })
@Html.ValidationMessageFor(model => model.DATE_ATTENDED)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.COURSE_COST)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.COURSE_COST, new { @class="FormTextBox" })
@Html.ValidationMessageFor(model => model.COURSE_COST)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.COURSE_RESITS, "Resits")
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.COURSE_RESITS, new { @class="FormTextBox" })
@Html.ValidationMessageFor(model => model.COURSE_RESITS)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.PROVIDER_ID, "Provider")
</div>
<div class="editor-field">
@Html.DropDownList("PROVIDER_ID", String.Empty)
@Html.ValidationMessageFor(model => model.PROVIDER_ID)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.EMP_COURSE_STATUS_ID, "Status")
</div>
<div class="editor-field">
@Html.DropDownList("EMP_COURSE_STATUS_ID", String.Empty)
@Html.ValidationMessageFor(model => model.EMP_COURSE_STATUS_ID)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.VENUE_ID, "Venue")
</div>
<div class="editor-field">
@Html.DropDownList("VENUE_ID", String.Empty)
@Html.ValidationMessageFor(model => model.VENUE_ID)
</div>
</td>
</tr>
</table>
<div>
<h2>Select Employees</h2>
<label for="required">Attendees</label>
@(Html.Kendo().MultiSelect()
.Name("required")
.DataTextField("fullName")
.DataValueField("employeeId")
.Placeholder("Select Attendees")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("Employees_Read", "Employee");
})
.ServerFiltering(true);
})
)
<button class="k-button" id="get">Add Course</button>
</div>
<p>
<input type="submit" value="MultiCreate" class="k-button" />
</p>
</fieldset>
}
<script>
$(document).ready(function () {
$("#EMPLOYEE_ID").width(350);
$("#EMPLOYEE_ID").height(25);
$("#PROVIDER_ID").width(350);
$("#PROVIDER_ID").height(25);
$("#COURSE_ID").width(350);
$("#COURSE_ID").height(25);
$("#VENUE_ID").width(350);
$("#VENUE_ID").height(25);
$("#EMP_COURSE_STATUS_ID").width(350);
$("#EMP_COURSE_STATUS_ID").height(25);
var required = $("#required").data("kendoMultiSelect");
var selectedItems = required.dataItems();
$("#get").click(function () {
var ids = [];
$(selectedItems).each(function () {
ids.push(this.employeeId);
});
$.ajax({
type: "POST",
url: "/EmployeeCourses/MultiCreate",
data: { empId: ids },
traditional: true
});
});
});
</script>
Update:
I've now created a view model and created a simple form and controller method. I can now pass the array of empIds back to the controller which is brilliant but the resto of the properties in the model are either null or zero! I'm getting the information for te kendo multi select from an ajax call so I'm wondering if that has anything to do with it. Does anyone have any ideas? Once I get this working the viewmodel / controller etc will be expanded to take more properties...
my view model looks like this:
namespace TrainingKendoUI.ViewModels
{
public class AddEmployeeCoursesViewModel
{
#region Constructors
public AddEmployeeCoursesViewModel()
{
}
public AddEmployeeCoursesViewModel(TRAINING_EMPLOYEE_COURSES model, int[] ids)
{
this.CourseId = model.COURSE_ID;
this.empIds = ids;
}
#endregion
#region Properties
public int CourseId { get; set; }
public int[] empIds { get; set; }
#endregion
}
}
and my controller method like this:
[HttpPost]
public ActionResult MultiCreateTest(AddEmployeeCoursesViewModel myCourses)
{
foreach(int myRow in myCourses.empIds)
{
if (ModelState.IsValid)
{
//Processing will happen here....
return RedirectToAction("Index", "EmployeeCourses", null);
}
}
ViewBag.COURSE_ID = new SelectList(db.TRAINING_COURSES, "COURSE_ID", "COURSE_NAME", myCourses.CourseId);
return View(myCourses);
}
and finally, my view looks like this:
@model TrainingKendoUI.ViewModels.AddEmployeeCoursesViewModel
@{
ViewBag.Title = "MultiCreateTest";
}
<h2>MultiCreateTest</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>TRAINING_EMPLOYEE_COURSES</legend>
<table>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => model.CourseId, "Course")
</div>
<div class="editor-field">
@Html.DropDownList("COURSE_ID", String.Empty)
@Html.ValidationMessageFor(model => model.CourseId)
</div>
</td>
<td>
<div class="editor-label">
@Html.Label("Attendees")
</div>
<div>
@(Html.Kendo().MultiSelect()
.Name("empIds")
.DataTextField("fullName")
.DataValueField("employeeId")
.Placeholder("Select Attendees")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("Employees_Read", "Employee");
})
.ServerFiltering(true);
})
)
</div>
<p>
<input type="submit" value="MultiCreate" class="k-button" />
</p>
</td>
</tr>
</table>
</fieldset>
}