0

I am attempting to use jQuery/AJAX/JSON in order to pass a value from an <input> on my main INV_Assets.Edit() View to my MVC5 controller method createNewModel(). There, the value is to be added to the database table INV_Models, and on successful return I want to refresh my dropdownlist so that it includes the new value.

However, when I run my current code (below) the value for alert(test) is coming up as garbage with RKW5IcXyLzel7mYJ7qqPMvrKIG8_wVv7obAJPx0NzRwgZ23QI_AmBYTOslxa290IWXYKsFSZI5xAVRL9R8JgCvm24DloP1aUBeBU_9jVVVA1 instead of (Ex.) 411.

DROPDOWN / NEW MODEL INPUT:

    <div class="form-group">
        @*@Html.LabelFor(model => model.Model_Id, "Model_Id", htmlAttributes: new { @class = "control-label col-md-2" })*@
        <span class="control-label col-md-2">Model:</span>
        <div class="col-md-4">
            @*@Html.DropDownList("Model_Id", null, htmlAttributes: new { @class = "form-control dropdown" })*@
            @Html.DropDownListFor(model => model.Model_Id, (SelectList)ViewBag.Model_List, htmlAttributes: new { @class = "form-control dropdown", @id = "selectModel" })
            @Html.ValidationMessageFor(model => model.Model_Id, "", new { @class = "text-danger" })
        </div>
        <div class="col-md-2">
            <div class="btn-group">
                <button id="createNewModel" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
            </div>
        </div>
        <div class="col-md-3">
            <div id="createModelFormContainer" style="display:none">
                <form action="/createNewModel">
                    <input type="text" name="model_description" />
                    <input type="button" id="submitNewModel" value="Submit" />
                </form>
            </div>
        </div>
    </div>

SCRIPT:

        $('#submitNewModel').click(function () {

            var form = $(this).closest('form');


            var test = form.find('input').first().val();
            alert(test);

            var data = { model_description: form.find('input').first().val() };
            alert(data.model_description);

            //var data = { model_description: $("input[name = 'model_description']").text.toString() };

            var jsonData = JSON.stringify(data);
            alert(jsonData.valueOf());

            $.ajax({
                type: "POST",
                dataType: "JSON",
                url: '@Url.Action("createNewModel", "INV_Assets")',
                data: jsonData,
                success: function (resp) {
                    alert("SUCCESS!");
                },
                error: function () {
                    alert("ERROR!");
                }
            });

INV_AssetsController - createNewModel():

    [HttpPost]
    public JsonResult createNewModel(INV_Models model)
    {

            model.created_date = DateTime.Now;
            model.created_by = System.Environment.UserName;
            model.modified_date = DateTime.Now;
            model.modified_by = System.Environment.UserName;

            // Set ID
            int lastModelId = db.INV_Models.Max(mdl => mdl.Id);
            model.Id = lastModelId+1;

            if (ModelState.IsValid == false && model.Id > 0)
            {
                ModelState.Clear();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    db.INV_Models.Add(model);
                    db.SaveChangesAsync();
                }
                catch (Exception ex)
                {
                    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
                }
            }

            return Json(new { ID = model.Id, Text = model.model_description });


    }

The idea is that each of my drop downs (6 others) contains values for other tables in the DB (Locations, Manufacturers, Models, Statuses, Types, Vendors) and the value from the dropdown which is selected is the value being set for my main INV_Assets entity properties of Locations, Manufacturer, etc.

I have Views set up for Create() of all the Other models individually, but on my INV_Assets.Edit() View I'm attempting to allow the user to press a button [CREATE NEW], enter a new value for the relevant table/model (Ex. Location) and then add that new location to the DB/as a dropdown option all without leaving the View.

For the life of me I can't figure out why my script variables are showing garbage instead of my entered values. When I break inside my controller checking ?model.model_description in the Immediate Window the value returned is null, so even the garbage being stored in my variable is not being passed to my controller.

Can someone with more experience weigh in on what the issue could be?


EDIT:

I changed form.find('input').first().val(); to document.getElementById('textNewModel').value }; and now the value is correctly being shown in my variables/alert, but it is NOT showing up in my Controller Action method -- ?model.model_description still returning null?


EDIT2:

Passing data in my ajax instead of jsonData variable, the value is correctly passing into the controller! However, the value is still not saving into the DB/Table? As a note, when the check if (ModelState.IsValid == false && model.Id > 0) the ModelState gets cleared -- I don't know if this could have something to do with it?

When the line return Json(new { ID = model.Id, Text = model.model_description }); is encountered, the values are valid, but on the return in my script alert("ID: " + data.ID + " // New Model: " + data.Text);T comes up with undefined for both...?

CURRENT SCRIPT:

        $('#submitNewModel').click(function () {

            var form = $(this).closest('form');
            var data = { model_description: document.getElementById('textNewModel').value };

            $.ajax({
                type: "POST",
                dataType: "JSON",
                url: '@Url.Action("createNewModel", "INV_Assets")',
                data: data,
                success: function (resp) {
                    alert("SUCCESS!");
                    $('#selectModel').append($('<option></option>').val(data.ID).text(data.Text));
                    alert("ID: " + data.ID + " // New Model: " + data.Text); // RETURNING 'undefined'...?
                    form[0].reset();
                    $('#createModelFormContainer').hide();
                },
                error: function () {
                    alert("ERROR!");
                }
            });

EDIT3:

As best I can figure the issue with the value not getting saved and perhaps the JSON not returning correctly is with my ModelState being invalid? I'm attempting to resolve exactly why my ModelState is coming up as invalid in my new Controller code:

    [HttpPost]
    public JsonResult createNewModel(INV_Models model)
    {

            model.created_date = DateTime.Now;
            model.created_by = System.Environment.UserName;
            model.modified_date = DateTime.Now;
            model.modified_by = System.Environment.UserName;

            // Set ID
            int lastModelId = db.INV_Models.Max(mdl => mdl.Id);
            model.Id = lastModelId+1;

            //if (ModelState.IsValid == false && model.Id > 0)
            //{
            //    ModelState.Clear();
            //}

            try
            {
                if (ModelState.IsValid) // INVALID???
                {
                    db.INV_Models.Add(model);
                    db.SaveChangesAsync();
                }

            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }

        return Json(new { ID = model.Id, Text = model.model_description }, JsonRequestBehavior.AllowGet);
    }

This is how my INV_Models is currently defined:

public class INV_Models

    {
        public int Id { get; set; }

        [Required(ErrorMessage = "Please enter a Model Description.")]
        public string model_description { get; set; }

        [Required]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime created_date { get; set; }

        [Required]
        public string created_by { get; set; }

        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime modified_date { get; set; }

        public string modified_by { get; set; }
    }
}

All the properties appear to be getting set, so I'm not sure why the ModelState is returning as Invalid?

tereško
  • 58,060
  • 25
  • 98
  • 150
Analytic Lunatic
  • 3,853
  • 22
  • 78
  • 120
  • 2
    Have you tried adding a class to the input instead of using the .first() selector? That would ensure that the first input on the page is indeed the field you think it is. – wolffer-east Feb 13 '15 at 16:16
  • Yea, I just tried adding an `ID` (EDIT above) which is now returning the correctly value in my variables/alerts, but the value is NOT getting passed to my controller. Any thoughts on this? – Analytic Lunatic Feb 13 '15 at 16:21
  • Did you also change `var data = { model_description: form.find('input').first().val() };` to `var data = { model_description: document.getElementById('textNewModel').value };`? Just to clarify before I dig deeper :) – wolffer-east Feb 13 '15 at 16:23
  • Lol, that is an excellent question! But yes, I did :) -- `var data = { model_description: document.getElementById('textNewModel').value };` – Analytic Lunatic Feb 13 '15 at 16:24
  • 1
    out of interest, what happens when you pass `data` instead of `jsonData` to the ajax method? – Ric Feb 13 '15 at 16:37
  • See my EDIT2 above. `data` does pass get the value into the controller! However, the value is still not getting saved / returned and added to the ` – Analytic Lunatic Feb 13 '15 at 16:47
  • Can you try this: `return Json(new { ID = model.Id, Text = model.model_description }, JsonRequestBehavior.AllowGet);` – Ric Feb 13 '15 at 17:03
  • Same result of `undefined`. I think something with my `ModelState` being invalid is causing the issue? New code above in `EDIT3`. – Analytic Lunatic Feb 13 '15 at 17:14
  • Do some debugging and find out the cause. Also savechangesasync may not finish before you return the json – Ric Feb 13 '15 at 17:18
  • Thanks Ric. I have no idea what to do regarding the `SaveChangesAsync()`. In the above EDIT I also added my `INV_Models` as it currently stands. With all the properties being filled, I'm not sure why the `ModelState` is showing as `Invalid`. – Analytic Lunatic Feb 13 '15 at 17:19
  • Try changing the method to SaveChanges – Ric Feb 13 '15 at 17:23
  • 3
    in your $.ajax success data.ID is undefined i think you mean resp.ID and resp.Text – Abraham Uribe Feb 13 '15 at 17:29
  • @Ric, Abraham was right about using `resp` vs `data` on the return to the script. I'm now trying to diagnose why my `ModelState` is coming up as `Invalid` due to `The created_by field is required` -- even though I have confirmed this value has been set before `TryValideModel()` is called? https://stackoverflow.com/questions/28505322/mvc5-modelstate-is-coming-up-as-invalid – Analytic Lunatic Feb 13 '15 at 20:02
  • That value looks suspiciously like the token that would be generated by `@Html.AntiForgeryToken();` which you probably added to the form that contains the dropdown. Which in turn means that you have the form for `` inside the main form tags, resulting in nested forms which is invalid html and not supported (and will cause other problems as well). Move this form outside the main form (although giving the textbox an `id` attribute does not hurt). –  Feb 14 '15 at 03:30

0 Answers0