locked
problem in saving data in edit modal for JQuery DataTable serverside mode RRS feed

  • Question

  • User-259252065 posted

    Hi. I'm implementing asp.net core 3.1 project and I have a JQuery DataTable in which I load data via server side into it. each row has an edit button by which after clicking by the user, it pops up a modal containing fields filled with related data. I need after the user clicks on save buttun in modal, the row that data being displayed as edited. Also the id of each row is different with its row number in DataTable. Here below is what I have tried so far and it shows me error like the following for (#login-btn).click function in site.js. right now I just want to recieve the edited data by json to ajax call in site.js.

    MyData controller:
    
    public class MyDataController : Controller
        {
            private readonly MyProjectContext _context;
    
            public MyDataController(MyProjectContext context)
            {
                _context = context;
            }
    
    [HttpPost]
            public JsonResult GetData()
            {
    
                try
                {
                    var draw = HttpContext.Request.Form["draw"].FirstOrDefault();
                    // Skiping number of Rows count  
                    var start = Request.Form["start"].FirstOrDefault();
                    // Paging Length 10,20  
                    var length = Request.Form["length"].FirstOrDefault();
                    // Sort Column Name  
                    var sortColumn = Request.Form["columns[" + Request.Form["order[0][column]"].FirstOrDefault() + "][name]"].FirstOrDefault();
                    // Sort Column Direction ( asc ,desc)  
                    var sortColumnDirection = Request.Form["order[0][dir]"].FirstOrDefault();
                    // Search Value from (Search box)  
                    var searchValue = Request.Form["search[value]"].FirstOrDefault();
    
                    //Paging Size (10,20,50,100)  
                    int pageSize = length != null ? Convert.ToInt32(length) : 0;
                    int skip = start != null ? Convert.ToInt32(start) : 0;
                    int recordsTotal = 0;
    
                    var customerData = from t1 in _context.customer
                                             
                                             select new
                                             {
                                                 id = t1.Id,
                                                 //DT_RowId=t1.Id.ToString(),
                                                 name = t1.Name,
                                                 phoneNumber = t1.PhoneNumber,
                                             };
    
    
    
                    if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDirection)))
                    {
                        customerData = customerData.OrderBy(sortColumn + " " + sortColumnDirection);
                    }
                    //Search  
                    if (!string.IsNullOrEmpty(searchValue))
                    {
                        customerData = customerData.Where(m => m.name == searchValue);
                    }
    
                    //total number of rows count   
                    recordsTotal = customerData.Count();
                    //Paging   
                    var data = customerData.Skip(skip).Take(pageSize).ToList();
                    //Returning Json Data  
                    return Json(new { draw = draw, recordsFiltered = recordsTotal, recordsTotal = recordsTotal, data = data });
    
                }
                catch (Exception)
                {
                    throw;
                }
    
            }
    
    }
    
    //-----------------------------------------------
    
    // GET: Transaction/AddOrEdit(Insert)
            // GET: Transaction/AddOrEdit/5(Update)
            public async Task<IActionResult> AddOrEdit(int id = 0)
            {
    
                if (id == 0)
                {
    
                    return View(new Customer());
                }
    
                else
                {
    
                    var Customer = await _context.Customer.FindAsync(id);
                    if (Customer == null)
                    {
                        return NotFound();
                    }
    
                    
                    return View(Customer);
    
                }
            }
    
    
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public async Task<IActionResult> AddOrEdit(int id, Customer Customer)
            {
    
                Customer re = new Customer();
                //if (ModelState.IsValid)
                //{
                //Insert
                if (id == 0)
                    {
    
                        if (ModelState.IsValid)
                        {
                            _context.Set<Customer>().Add(new Customer
                            {
    
                                Name = Customer.Name,
                           
                                PhoneNumber = Customer.PhoneNumber,
                                
                            });
    
                            await _context.SaveChangesAsync();
    
                        }
                    }
                    //Update
                    else
                    {
                        try
                        {
    
                            var entity = _context.Customer.FirstOrDefault(item => item.Id == id);
                            entity.Name = Customer.Name;
                            entity.PhoneNumber = Customer.PhoneNumber;
                                                
                            _context.Update(entity);
                            await _context.SaveChangesAsync();
    
                        //sending data to the Datatable
                        re = new Customer { 
                        Id = Customer.Id,
                        Name = Customer.Name,
                        PhoneNumber = Customer.PhoneNumber,
                        
                    };
    
                }
                        catch (DbUpdateConcurrencyException)
                        {
                            if (!CustomerExists(Customer.Id))
                            {
                                //return NotFound();
                                Console.WriteLine("Not Found");
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                return Json(re);
    
            }
         
    //----------------------------------------------------------------
    AddOrEdit.cshtml
    
    @model MyProject.Models.Customer
    
    @{
        Layout = null;
    }
    <head>
    
        <link rel="stylesheet" href="~/css/site.css" />
    
    </head>
    <body>
    
        <hr />
    
        <script src="~/js/site.js" asp-append-version="true" defer></script>
    
    
        <div class="row sub3">
            <div class="col-md-4">
    
                <form method="post" name="setting-form">
              
                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                    <input type="hidden" asp-for="Id" />
                    <div class="form-group">
                        <label asp-for="Name" class="control-label mylabel">name</label>
                        <input asp-for="Name" class="form-control" />
                        <span asp-validation-for="Name" class="text-danger"></span>
                    </div>
    
               
                    <div class="form-group">
                        <label asp-for="PhoneNumber" class="control-label mylabel">phone number</label>
                        <input asp-for="PhoneNumber" class="form-control" />
                        <span asp-validation-for="PhoneNumber" class="text-danger"></span>
                    </div>
                
                    <div class="form-group">
                        <input type="submit" value="save" class="btn btn-primary" id="login-btn"/>
                    </div>
                </form>
            </div>
        </div>
    
    
    </body>
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    
    
    
    //----------------------------------------------------------------
    _ViewAll.cshtml
    
    @model IEnumerable<MyProject.Models.Customer>
    
    
    <head>
        <link href="~/css/DataTable/jquery.dataTables.css" rel="stylesheet" type="text/css" />
        <link href="~/contents/Index.css" rel="stylesheet" type="text/css" />
    </head>
    
    
    <script>
    
        jQuery(document).ready(function ($) {
    
            $("#myDummyTable").DataTable({
    
                "processing": true, // for show progress bar
                "serverSide": true, // for process server side
                "filter": true, // this is for disable filter (search box)
                "orderMulti": false,
               
                "ajax": {
                    "url": "MyData/GetData",
                    "type": "POST",
                    "datatype": "json",
                },
                "columnDefs": [{
                    "targets": [0],
                    "visible": false,
                    "searchable": false
                }],
    
              rowId: "id",
              select: true,
    
                 "columns": [
                    { "data": "id", "name": "Id", "autoWidth": true },
                    { "data": "name", "name": "Name", "autoWidth": true },
               
                    { "data": "phoneNumber", "name": "PhoneNumber", "autoWidth": true },
                
    
                     {
                         "data": "id",
                         "searchable": false,
                         "sortable": false,
                         render: function (data, type, row, meta) {
                            
                            return "<a class='btn btn-primary' onclick=editClick('" + row.id+ "'); >edit</a>";
                       
                         }
                     }
                
                ]
    
            });
    
    
          
    });
    
    
    
         function editClick(obj) {
             
    
           
             var tempurl = '@Url.Action("AddOrEdit","MyData")'+'/'+obj;
             
             var link = document.createElement("a");
             link.href = tempurl
    
             
             var url = link.protocol + "//" + link.host + link.pathname + link.search + link.hash;
             
             showInPopup(url,'edit');
    
        };
    
    
    </script>
    
    <div id="tablecontainer" class="my-5 col-sm-12 p-4">
        <table id="myDummyTable" class="table m-table mytable table-striped table-bordered mb-4 dt-responsive nowrap">
            <thead>
                <tr>
                    <th>
                        ID
                    </th>
                    <th>
                       name
                    </th>
                    
                    <th>
                        phone number
                    </th>
                   
                    <th></th>
                </tr>
            </thead>
            <tbody>
           
            </tbody>
        </table>
    </div>
    //--------------------------------------------------------------------------------------------------
    Here is Index
    
    @model IEnumerable<MyProject.Models.Customer>
    
    
    @{ ViewData["Title"] = "Index"; }
    
    <div id="view-all">
        @await Html.PartialAsync("_ViewAll", Model)
    </div>
    
    @section Scripts{
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    
    
    
    //-------------------------------------------------------------------------------------------------
    //Here is _Layout in which I defined modal
            
                <div class="modal" tabindex="-1" role="dialog" id="form-modal">
                    <div class="modal-dialog" role="document">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title"></h5>
                                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                    <span aria-hidden="true">×</span>
                                </button>
                            </div>
                            <div class="modal-body">
    
                            </div>
                        </div>
                    </div>
                </div>
              
    
    //------------------------------------------------------------------
    My site.js
    
    showInPopup = (url, title) => {
        console.log('url:'+url);
        try {
        $.ajax({
            type: 'GET',
            url: url,
            contentType: false,
            processData: false,
    
            success: function (res) {
               
                $('#form-modal .modal-body').html(res);
               
                $('#form-modal .modal-title').html(title);
               
                $('#form-modal').modal('show');
               
    
            },
             error: function (err) {
                 console.log('error get:' + err);
            }
        })
       
        return false;
    } catch (ex) {
        console.log(ex)
      }
    }
    ///////////////////////////////////////////////////
    $(document).ready(function () {
        $("#login-btn").click(function (event) {
    
            event.preventDefault();
            try {
                $.ajax({
                    url: "customers/AddOrEdit",
                    type: "POST",
                    datatype: "json",
                  
                    success: function (response) {
                        $.each(response, function (index, value) {
    
                            console.log(value.name);
                        })
                    },
                    error: function (data, status) {
                        console.log('error is login-btn:');
                        console.log(status);
                    }
                })/*;*/
            }
              catch (ex) {
                console.log('error try catch:'+ex);
        }
            //alert("do what ever you want");
        });
    });
    //------------------------------------------------------------------
    

    The error is like the following in browser console:

    error is login-btn:
    error
    XML Parsing Error: no root element found
    Location: https://Localhost:44357/Customers/AddOrEdit
    Line Number 1, Column 1:


     

    Monday, February 15, 2021 3:33 PM

Answers

  • User475983607 posted

    Thank you for your answer. But how can I submit data in AddOrEdit so sending it to ajax then?

    I focused on the AddOrEdit logic and build a basic example based on your code.   I think it is important to mention that your code is very confusing and does not make much logical sense.  So I'm not sure if the example will help much but it does show how to submit data in an AJAX post.

    public class UserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string PhoneNumber { get; set; }
    }
    
    public class CustomersController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    
        [HttpPost]
        public IActionResult AddorEdit(UserModel user)
        {
            return Json(user);
        }
    }
    @model MvcDemo.Controllers.UserModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <div class="row">
        <div class="col-md-4">
            <form method="post" name="setting-form">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <input type="hidden" asp-for="Id" />
                <div class="form-group">
                    <label asp-for="Name" class="control-label mylabel">name</label>
                    <input asp-for="Name" class="form-control" value="Hello" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
    
    
                <div class="form-group">
                    <label asp-for="PhoneNumber" class="control-label mylabel">phone number</label>
                    <input asp-for="PhoneNumber" class="form-control" value="123-4567" />
                    <span asp-validation-for="PhoneNumber" class="text-danger"></span>
                </div>
    
                <div class="form-group">
                    <input type="submit" value="save" class="btn btn-primary" id="login-btn" />
                </div>
            </form>
        </div>
    </div>
    
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    
    <script>
        $(document).ready(function () {
            $("#login-btn").click(function (event) {
                event.preventDefault();
                try {
                    $.ajax({
                        url: "customers/AddOrEdit",
                        type: "POST",
                        datatype: "json",
                        data: $('form').serialize(),
                        success: function (response) {
                            console.log(response);
                        },
                        error: function (data, status) {
                            console.log('error is login-btn:');
                            console.log(status);
                        }
                    });
                }
                catch (ex) {
                    console.log('error try catch:' + ex);
                }
            });
        })
    </script>
    }
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 15, 2021 6:56 PM

All replies

  • User475983607 posted

    Elenorarez, I only reviewed the AddOrEdit logic.  Just this little bit of code contains lot of logical and design bugs.   These bugs should be easy to find using the debugging tools that come with Visual Studio and the browser (dev tools).  

    The AJAX function that calls /Customers/AddOrEdit, which causes the error "no root element found",  does not submit data.  The AddorEdit() action does not handle model errors.   If the action throws an exception, there is a high probability the catch block will also throw an exception.  The catch assumes Customer.Id exist which it does not in your current code because both the action input parameters and not sent.  Therefore Id is always defaults to zero.

    I'm not a fan of the Add/Edit action because it requires complex logic that is difficult to debug.  Creating two separate method is much easier to code and debug.  If you think about how the Add/Edit works, it is based on the existence of a primary key.  The client already knows if the user is creating a new record or not.   The client can simply call Add or Insert directly. 

    Monday, February 15, 2021 4:40 PM
  • User-259252065 posted

    Thank you for your answer. But how can I submit data in AddOrEdit so sending it to ajax then?

    Monday, February 15, 2021 6:04 PM
  • User475983607 posted

    Thank you for your answer. But how can I submit data in AddOrEdit so sending it to ajax then?

    I focused on the AddOrEdit logic and build a basic example based on your code.   I think it is important to mention that your code is very confusing and does not make much logical sense.  So I'm not sure if the example will help much but it does show how to submit data in an AJAX post.

    public class UserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string PhoneNumber { get; set; }
    }
    
    public class CustomersController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    
        [HttpPost]
        public IActionResult AddorEdit(UserModel user)
        {
            return Json(user);
        }
    }
    @model MvcDemo.Controllers.UserModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <div class="row">
        <div class="col-md-4">
            <form method="post" name="setting-form">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <input type="hidden" asp-for="Id" />
                <div class="form-group">
                    <label asp-for="Name" class="control-label mylabel">name</label>
                    <input asp-for="Name" class="form-control" value="Hello" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
    
    
                <div class="form-group">
                    <label asp-for="PhoneNumber" class="control-label mylabel">phone number</label>
                    <input asp-for="PhoneNumber" class="form-control" value="123-4567" />
                    <span asp-validation-for="PhoneNumber" class="text-danger"></span>
                </div>
    
                <div class="form-group">
                    <input type="submit" value="save" class="btn btn-primary" id="login-btn" />
                </div>
            </form>
        </div>
    </div>
    
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    
    <script>
        $(document).ready(function () {
            $("#login-btn").click(function (event) {
                event.preventDefault();
                try {
                    $.ajax({
                        url: "customers/AddOrEdit",
                        type: "POST",
                        datatype: "json",
                        data: $('form').serialize(),
                        success: function (response) {
                            console.log(response);
                        },
                        error: function (data, status) {
                            console.log('error is login-btn:');
                            console.log(status);
                        }
                    });
                }
                catch (ex) {
                    console.log('error try catch:' + ex);
                }
            });
        })
    </script>
    }
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 15, 2021 6:56 PM
  • User-259252065 posted

    Thank you very much, your answer helped me a lot.

    Tuesday, February 16, 2021 11:13 AM