0

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>
}

2 Answers2

0

You need to create a view model containing all the information you need, then have that get passed back to the controller. So, your ViewModel will contain a

TRAINING_EMPLOYEE_COURSES, the courseId, and and array of empId

public TrainingCourseCreationViewModel
{
   public TRAINING_EMPLOYEE_COURSES TrainingCourse { get; set;}
   public int courseId { get; set;}
   public int[] empId { get; set;}
}

Have your create view use this model instead of the TRAINING_EMPLOYEE_COURSES model, then have this be the model passed into the ActionResult.

For more information of ViewModels in MVC read here

http://stackoverflow.com/questions/16548376/asp-net-mvc-how-exactly-to-use-view-models

View Models are essential when creating an ASP.NET MVC application, they should be used for every View in you application to pass data back to you controllers, then the values should be mapped to your data or domain Models.

Dan
  • 1,450
  • 1
  • 17
  • 34
  • HI Dan, thanks for the help. Yep, I'll create a viewModel but the bit I'm struggling with is how I get the array that I've created in the javascript passed back along with the model (sorry, I'm a bit new to this so please bear with me!) – user2883382 Feb 18 '14 at 16:09
  • In your view you should have a multiselect with a name attribute of empId. That should bind to the property of your view model with the same name. If not use developer tools (F12 in your browser) and check the actual post when you submit the form. This will tell you what is being sent back to the server. You should see a list of values all called empId, this should bind to the int[] empId on your view model. You can explicitly list each property being sent back to the server if you wish. – Dan Feb 18 '14 at 16:26
0

You're only sending the employee ids in your post:

$.ajax({
    type: "POST",
    url: "/EmployeeCourses/MultiCreate",
    data: { empId: ids },    // This is what will be used to populate your view model
    traditional: true
});

Which is why that's the only thing getting populated. You also need to send the CourseId; I think the form field will be called "COURSE_ID" based on your code, so something like this should work:

var $courseId = $("#COURSE_ID");

$.ajax({
    type: "POST",
    url: "/EmployeeCourses/MultiCreate",
    data: {
        empId: ids,
        CourseId: $courseId.val()
    },
    traditional: true
});
gerrod
  • 6,119
  • 6
  • 33
  • 45