2

I am new to MVC, I am trying to edit a row and sending edited data to a controller method via jQuery and AJAX, when I click on edit the specific row becomes textboxes and save ActionLink appears instead of edit, but when I save it it gives me an exception because null is going in data

jQuery/Ajax Code:

$(document).ready(function () {
            function toggleEditability() {
                $(this).closest('tr')
                       .find('a.Edit, a.Save, .displayText, input[type=text]')
            }

            $('a.Edit').click(toggleEditability);

            $('a.Save').click(function () {
                toggleEditability.call(this);
                var data = $(this).closest('tr').serialize();   
                alert(data);
                //var url = $(this).attr('href');
                var actionURL = '@Url.Action("Edit", "Holiday")';
                $.ajax({
                    url: actionURL,             // Url to send request to
                    data:data,           // Send the data to the server
                    type: "POST",         // Make it a POST request
                    dataType: "html",     // Expect back HTML
                    success: function (html) {
                        $("#dialog-edit").dialog('open');      
                    }
                });
            });
        });

alert(data) is showing this enter image description here

chtml code:

   <div id="details">
    <table>
        <tr>
            @*<th>
                @Html.Label("ID")
            </th>*@
            <th>
                @Html.Label("Name")
            </th>
            <th>
                @Html.Label("Description")
            </th>
            <th>
                 @Html.Label("Date")
            </th>
            <th></th>
        </tr>

    @foreach (var item in Model)
    {
        if (Convert.ToDateTime(item.Holiday_date).Year.ToString() == DateTime.Now.Year.ToString())
        {
            <tr>
           @* <td>
                @Html.TextBoxFor(modelItem => item.Holiday_Id, new { style = "display: none; width:170px; height:15px" })
                <div class="displaytext">
                    @Html.DisplayFor(modelItem => item.Holiday_Id)
                </div>
            </td>*@
            <td>
                <div class="HolidayName">
                    @Html.TextBoxFor(modelItem => item.Holiday_Name,  new { id = "", style = "display: none; width:170px; height:15px" })
                </div>
                <div class="displaytext">
                    @Html.DisplayFor(modelItem => item.Holiday_Name)
                </div>
            </td>
            <td>
                <div class="HolidayDescription">
                    @Html.TextBoxFor(modelItem => item.Holiday_Description, new { id = "", style = "display: none; width:170px; height:15px" })
               </div>
               <div class="displaytext">
                    @Html.DisplayFor(modelItem => item.Holiday_Description)
                </div>
            </td>
            <td>
                <div class="HolidayDate">
                    @Html.TextBoxFor(modelItem => item.Holiday_date, new { id = "", style = "display: none; width:170px; height:15px" })
                </div>
                <div class="displaytext">
                    @Html.DisplayFor(modelItem => item.Holiday_date)
                </div>
            </td>
            <td>
               @Html.ActionLink("Edit", "Edit", new { id = item.Holiday_Id }, new { @class = "Edit", Href="#" })
               @Html.ActionLink("Save", "Save", new { id = item.Holiday_Id}, new { @class = "Save", Href = "#", style = "display:none" } ) |
               @Html.ActionLink("Delete", "Delete", new { id = item.Holiday_Id }, new { @class = "lnkDelete" })
               @Html.ActionLink("Cancel", "Cancel", new { id = item.Holiday_Id}, new { @class = "Cancel", Href = "#", style = "display:none" } )
            </td>
        </tr>
        }

    }

    </table>

   </div>

Controller Method Code:

 public ActionResult Edit(tbl_HolidayList tbl_holidaylist)
        {
            if (ModelState.IsValid)
            {
                db.Entry(tbl_holidaylist).State = EntityState.Modified;
                db.SaveChanges();
                TempData["Msg"] = "Data has been updated succeessfully";
                return RedirectToAction("Index");
            }
            return PartialView(tbl_holidaylist);
        }

tbl_HolidayList.cs

namespace OTESSystem.Models
{
    using System;
    using System.Collections.Generic;

    public partial class tbl_HolidayList
    {
        public int Holiday_Id { get; set; }
        public string Holiday_Name { get; set; }
        public string Holiday_Description { get; set; }
        public Nullable<System.DateTime> Holiday_date { get; set; }
    }
}

Can you tell me how to get the textboxes values in data for jQuery to save it?

exception and data coming null in method: enter image description here

3
  • need to isolate where your problem is ... client or server code. What are you seeing in alert(data); Commented Jan 6, 2015 at 20:01
  • I updated the question what alert(data) is showing Commented Jan 6, 2015 at 20:05
  • 1
    make sure u have specified name attribute of all input element. check out this fiddle jsfiddle.net/U3bRg/280 Commented Jan 7, 2015 at 4:36

5 Answers 5

4

You're getting null for alert(data) because you're trying to serialize the entire content of the closest tr and it contains non-input controls as well. So try to serialize just the input controls like below

var data = $(this).closest('tr').find('input').serialize();
alert(data);

and your alert should return you the tr data as shown below in the image.

enter image description here

If your AJAX posted model data returns null at the Save action then an alternate would be to build your data array from the serialized data object and take only what you would require something like below (all the below code within your $('a.Save').click(function () { ... )

var dataArray = $(this).closest('tr').find('input').serialize();
dataObj = {};

 // loop through and create your own data object
 $(dataArray).each(function (i, field) {
      dataObj[field.name] = field.value;
 });

 var data = {};
 data.Holiday_Id = dataObj['item.Holiday_Id'];
 data.Holiday_Name = dataObj['item.Holiday_Name'];
 data.Holiday_Description = dataObj['item.Holiday_Description'];
 data.Holiday_date = dataObj['item.Holiday_date'];

 var actionURL = '@Url.Action("Save", "Holiday")';

 $.ajax({
        url: actionURL,  // Url to send request to
        data: JSON.stringify({ model: data }),  // Send the data to the server
        type: "POST",    // Make it a POST request
        dataType: "html", // Expect back HTML
        contentType: 'application/json; charset=utf-8',
        success: function (html) {
             $("#dialog-edit").dialog('open');
        }
      });

And now you should see the posted data at the controller's Save action.

enter image description here

UPDATE 1: Based on the error noted in your comment it seems like your primary key is coming as null to the controller's action method. You can add a hidden input field to the markup as shown below.

.....

<td>
     @Html.DisplayFor(modelItem => item.Holiday_Id)
     @Html.HiddenFor(modelItem => item.Holiday_Id);
</td>

....
Sign up to request clarification or add additional context in comments.

8 Comments

I tried var data = $(this).closest('tr').find('input').serialize(); alert(data); it is showing the data in alert but in the controller method it is still giving me exception on SaveChanges() method Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
I think value for Holiday_Id is coming as null to the controller's action. Since you don't have an input element in the HTML markup for the primary key just add a hidden field @Html.HiddenFor(modelItem => item.Holiday_Id); in your view. Make sure your Save action's parameter has all necessary values required for SaveChanges(). Editing the answer with the required markup.
I added a hidden field @Html.HiddenFor(modelItem => item.Holiday_Id); and I can see the Holiday_Id in alert but still the same exception.
Did changing to db.Entry(tbl_holidaylist).State = EntityState.Add; instaed of db.Entry(tbl_holidaylist).State = EntityState.Modified; help? I think it could be something related to the issue reported here or here or here
db.Entry(tbl_holidaylist).State = EntityState.Modified; that statement has nothing to do if data is coming null, kindly check the image I updated in the question
|
1

since serialize isn't returning anything I would recommend you grab the fields you want instead of serializing the row. change

data = $(this).closest('tr').serialize();

to this in your ajax call

data: { 
    Holiday_id : $(this).closest('tr').find(".Holiday_id").val(), 
    Holiday_Name : $(this)...
},

8 Comments

use classes since ID's can't repeat
its still giving me null in alert
@UmmEHabibaSiddiqui if you change the alert to alert(data.Holiday_id); does it show something?
change your alert to the $this part of the line to confirm that it is finding the value. With my changed code it will be looking for class="Holiday_id" so make sure that is showing on your fields
it isn't finding the value, still it is saying undefined and getting an exception of null reference "values can not be null" in controller method
|
1

Jquery serialize() won't serialize the value in which element name attribute is not set. Make sure you have specified name attribute to all input element.

You have to specify name attribute too in your razor code.

@Html.TextBoxFor(modelItem => item.Holiday_Name,  
                 new { id = "", name="HolidayName", 
                 style = "display: none; width:170px; height:15px" })

According to JQuery documentation

Only "successful controls" are serialized to the string. No submit button value is serialized since the form was not submitted using a button. For a form element's value to be included in the serialized string, the element must have a name attribute. Values from checkboxes and radio buttons (inputs of type "radio" or "checkbox") are included only if they are checked. Data from file select elements is not serialized.

Checkout this fiddle

And one more thing you need to modify in your code is following line.

var data = $(this).closest('tr').find('input').serialize();   

because only those element can be serialized which has name attribute and you have only input elements in your code.

2 Comments

I tried var data = $(this).closest('tr').find('input').serialize(); alert(data); it is showing the data in alert but in the controller method it is still giving me exception on SaveChanges() method Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Make sure you are not using another object of DatabaseContext (db) anywhere else. It happens because if you use more than one DBContext object at a time and you are updating data from one db object so, it will not be affected in another one. try to use using (DbContext db = new DbContext()) instead of public object in your method. read this post BTW, you have solved your first issue.
0

Sounds like your public ActionResult Edit(tbl_HolidayList tbl_holidaylist) method is supposed to be accepting JSON and returning it back.

Try something like this and walk through your code to see where you fail:

public JsonResult Edit(tbl_HolidayList model)
{
    var hlist = db.tbl_holidaylists.Where(x => x.Id = model.Id).FirstOrDefault();

    hlist = model; // something like this to overwrite the existing values...

    db.SaveChanges();

    return Json(hlist);
}

Lastly, change your AJAX success callback to see what you get back like so:

success: function (html) {
    console.log(html);
}

3 Comments

Change to .Where() which is a linq function. Also, it was just an example since I don't know your schema
it isn't working because data is coming null from view
See @Dennis R's answer as it is more complete. Basically, you need to send an object to your JsonResult Edit() action which matches your model.
0

Try this, first modify your view to have some identifiers for the fields you need in the rows.

@Html.TextBoxFor(modelItem => item.Holiday_Id, new { @class = "holidayId"})
@Html.TextBoxFor(modelItem => item.Holiday_Name,  new { @class = "holidayName" })
@Html.TextBoxFor(modelItem => item.Holiday_Description, new { @class = "holidayDescription" })
@Html.TextBoxFor(modelItem => item.Holiday_date, new { @class = "holidayDate" })

Then change your ajax calls data to be this:

var data = {};
data.Holiday_Id = $(this).closest('tr').find(".holidayId").val();
data.Holiday_Name = $(this).closest('tr').find(".holidayName").val();
data.Holiday_Description = $(this).closest('tr').find(".holidayDescription").val();
data.Holiday_Date = $(this).closest('tr').find(".holidayDate").val();

Test the alert, and if the alert has the data, then set a break point on your controllers action method and see if the parameter is coming through filled in.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.