MVC Question Regarding Passing Lists to the Controller

Crystal Rouse
Crystal Rouse used Ask the Experts™
on
I am trying to use jQuery SelectListActions in an Update Form.  I need to pass the results of the 2nd listbox to my controller.  I don't have a View Model for this View since I am updating data and already have the data populated on the form from a Table with a variable passed to it.  The 2nd List Box is not defined in the Model but I need to get the contents of it and pass to my controller.  Is there a way to do this?  I really just need to get a list of data from a Multi-Select List Box back to my controller.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
ǩa̹̼͍̓̂ͪͤͭ̓u͈̳̟͕̬ͩ͂̌͌̾̀ͪf̭̤͉̅̋͛͂̓͛̈m̩̘̱̃e͙̳͊̑̂ͦ̌ͯ̚d͋̋ͧ̑ͯ͛̉Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015

Commented:
This isn't really a JQuery problem. You simply need to assign a name to your <select> control, and then in your controller add a parameter that is of type List (or array) and model binding should take care of loading the selected values into the list.

e.g.

Controller
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Title = "Home Page";

            return View();
        }

        [HttpPost]
        public ActionResult Index(string[] options)
        {
            return View();
        }
    }
}

Open in new window


View
<form method="post">
    <select name="options" multiple>
        <option></option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
    </select>
    <button type="submit">Submit</button>
</form>

Open in new window


Note how the <select> has a name attribute that matches the name of the controller action's parameter.

Screenshot
If you're using JQuery to submit the values via AJAX, then the process isn't much different--just make sure that the object you POST to the server has a parameter name that matches the parameter of the controller, and make the value an array of the selected options.
Crystal RouseTask Lead

Author

Commented:
When I try this options just comes thru as Null.

Controller:
 public ActionResult UpdateLocation([Bind]tbl_SystemLocationData formData, string sys, string[] options)

Open in new window


View:

                                    @Html.DropDownList("options", sl.getAssets(Model[j].System), new
                               {
                                   @class = "form-control",
                                   @multiple = "multiple",
                                   @id = "options"
                               })

Open in new window

ǩa̹̼͍̓̂ͪͤͭ̓u͈̳̟͕̬ͩ͂̌͌̾̀ͪf̭̤͉̅̋͛͂̓͛̈m̩̘̱̃e͙̳͊̑̂ͦ̌ͯ̚d͋̋ͧ̑ͯ͛̉Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015

Commented:
How is the data being submitted to the server? What does the raw request look like? Are you performing a POST or a GET?
Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

Crystal RouseTask Lead

Author

Commented:
I think the problem is that I am using jQuery to move the options I want to a 2nd drop-down list. I need to get all of the options in the 2nd dropdown list to my controller.  It is coming thru as null possibly because nothing is actually selected.
ǩa̹̼͍̓̂ͪͤͭ̓u͈̳̟͕̬ͩ͂̌͌̾̀ͪf̭̤͉̅̋͛͂̓͛̈m̩̘̱̃e͙̳͊̑̂ͦ̌ͯ̚d͋̋ͧ̑ͯ͛̉Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015

Commented:
Are you submitting the form using JQuery, or are you submitting through a regular-old HTML button? If the latter, then yes, you would need to mark the items selected (via JQuery). If the former, then just grab all the items from the 2nd DDL using JQuery.
Crystal RouseTask Lead

Author

Commented:
I'm submitting using a Form with a submit button:

@using (Html.BeginForm("UpdateLocation", "Location", FormMethod.Post, new
    {[code]
        name = "EditForm",

    }))

Open in new window


I also have a JavaScript include file with validation and a submit function:  The validation works, I just need to figure out how to pass the
option list to my controller.


 Validate: function () {
        var valid = true;

        var assets = document.getElementById("Assets");
            var assetTxt = "All options: ";
            var i;
            for (i = 0; i < assets.length; i++) {
                assetTxt = assetTxt + "\n" + assets.options[i].value;               
            }
}


 formSubmit: function () {

        event.preventDefault();

        var assets = document.getElementById("Assets");
        assetOptions = [];
        var i;
        for (i = 0; i < assets.length; i++) {
            assetOptions = assets.options[i].value;
        }
        alert(assetOptions);

        if (this.Validate())
       document.forms["EditForm"].submit();
    },

Open in new window

ǩa̹̼͍̓̂ͪͤͭ̓u͈̳̟͕̬ͩ͂̌͌̾̀ͪf̭̤͉̅̋͛͂̓͛̈m̩̘̱̃e͙̳͊̑̂ͦ̌ͯ̚d͋̋ͧ̑ͯ͛̉Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015

Commented:
Another, less desirable approach (IMO), would be to append a new hidden element to the form when you shift the items from one list to the other:

<form method="post" id="formdiv">
    <select id="available" multiple>
        <option></option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
    </select>
    <select id="options" multiple disabled="disabled"></select>
    <button type="submit">Submit</button>
</form>

@section scripts
{
    <script>
        (function () {
            $('option').on('dblclick', function (evt) {
                var element = $(evt.target);
                var hidden = $('<input type="hidden" />');

                element.remove()
                    .removeAttr('selected');

                hidden.val(element.val())
                    .attr('name', 'options[' + $('#options option').length + ']');

                $('#options').append(element[0]);
                $('#formdiv').append(hidden);
            });
        })();
    </script>
}

Open in new window


In the above, we create a new hidden element who has the value from the <option> we shifted. The important bit is naming the new hidden element with the name of the receiving property on the controller, and then using an array-like syntax to indicate that it will belong to a collection on the server. Model binding will take care of populating the controller parameter correctly:

 Screenshot
You'd need to add code to remove the <input type="hidden" /> elements if you allow elements to be removed from the second list.
Crystal RouseTask Lead

Author

Commented:
I can get the data to the controller using Json.  I now need help using it - figuring out how to serialize.

 public tbl_SystemLocationData()
        {
            this.AssetListJson = new List<string>();
        }

        public List<string> AssetListJson { get; set; }

Open in new window


The data comes thru to my controller as Json (I've attached an image of the results).


  public ActionResult UpdateLocation([Bind]tbl_SystemLocationData formData)
{

 if (!ModelState.IsValid)
            {

                return View(SystemReport());
            }

            try
            {
                //JavaScriptSerializer serializer = new JavaScriptSerializer();
                //formData.AssetListJson = serializer.Deserialize<List<tbl_SystemLocationData>>(formData.AssetListJson);

Open in new window


I have a hidden form element:

    @using (Html.BeginForm("UpdateLocation", "Location", FormMethod.Post, new
    {
        name = "EditForm",

    }))
    {
        for (int j = 0; j < Model.Count; j++)
        {
             @Html.Hidden("AssetListJson", Model[j].AssetListJson)
            break;
        }

Open in new window


The JavaScript looks like this:

 formSubmit: function () {

        event.preventDefault();

        assetList = [];
        var assets = document.getElementById("Assets");

        for (var i = 0; i < assets.length; i++) {
            assetList.push({
                "Asset": assets.options[i].value
            });
        }

        document.getElementById("AssetListJson").value = JSON.stringify(assetList);

        if (this.Validate())
       document.forms["EditForm"].submit();
    },

Open in new window


Now, I need help figuring out how to serialize the Json Results.  Any help appreciated!
Json-results.PNG
Crystal RouseTask Lead

Author

Commented:
If I send the data in JavaScript as a string:

 var assets = document.getElementById("Assets");
        var assetValue = "";
        var i;
        for (i = 0; i < assets.length; i++) {
            assetValue = assetValue + "," + assets.options[i].value;
        }

         var assetListJson = document.getElementById("AssetListJson");
         assetListJson.value = assetValue;

Open in new window


How do I loop thru the value to split by the commas?  Ive tried this in the controller:

 List <string> assetList = formData.AssetListJson;

                if (assetList.Count > 0)
                {
                    foreach(var record in assetList)
                    {
                        var item = assetList.ToString().Split(',');
                    }
                   
                }

Open in new window

Task Lead
Commented:
I was able to get this working with some minor changes in the controller.

                List <string> assetList = formData.AssetList;

                if (assetList.Count > 0)
                {
                    for (int j = 0; j < assetList.Count; j++)
                    {
                        var assetID = assetList[j].ToString().Split(',');

                        foreach (var item in assetID)
                        {
                            if (!String.IsNullOrEmpty(item))
                            {
                                int assetItem = Convert.ToInt32(item);

                                List<tbl_Data> details = (from x in DB.tbl_Data
                                                                  where x.id == assetItem
                                                                  select x).ToList();

                                foreach (tbl_Data record in details)
                                {
                                    record.loc_ID = data.id;
                                    record.modifiedDate = DateTime.Now;

                                    DB.SaveChanges();
                                }
                            }                         

                        }

                      }
                }

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial