Search code examples
c#ajaxasp.net-mvcasp.net-mvc-5jquery-bootgrid

Update grid with added record from AJAX Post, MVC 5


I've seen quite a few posts on this, but I wanted to try to get a best practice down before going down the route I think I will likely need to go. I'm attempting to update my view after I've inserted a new record into the database:

Pretty basic set-up:

<table id="grid-basic" class="table table-condensed table-hover table-striped">
    <thead>
        <tr>
            <th data-column-id="role_id">ID</th>
            <th data-column-id="description">Description</th>
            <th data-column-id="commands" data-formatter="commands" data-sortable="false">Commands</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>@item.Id</td>
                <td>@item.Name</td>
            </tr>
        }
    </tbody>
    <tfoot>
        <tr>
            <td></td>
            <td style="padding-right: 20px;">
                <div id="add-role-text-group" class="form-group">
                    <input id="add-role-text" type="text" class="form-control input-md" placeholder="Add Role" data-container="body" title="A role description must be entered."/>
                    <span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>
                </div>
            </td>
            <td style="vertical-align: middle;"><button type="button" class="btn btn-xs btn-default command-add"><span class="fa fa-plus"></span></button></td>
        </tr>
    </tfoot>
</table>

My C# code

// GET: Application Role Management
        [Route("role")]
        public ActionResult Role()
        {
            return View(RoleManager.Roles.ToList<IdentityRole>());
        }

        [HttpPost]
        [Route("addrole")]
        public async Task<ActionResult> AddRole(string description)
        {
            IdentityRole role = new IdentityRole();
            role.Name = description;

            var result = await RoleManager.CreateAsync(role);
            if (result.Succeeded)
            {
                return RedirectToAction("role");
            } else {
                return RedirectToAction("Error");
            }
        }

AJAX POST

$.ajax({
     type: "POST",
     url: "@Url.Action("AddRole")", // the method we are calling
     contentType: "application/json; charset=utf-8",
     data: JSON.stringify({ description: $element.val() }),
     dataType: "json"
});

I load the View, grab all the roles in the system and display into a grid. I have an inline row for insertion of a new role. I type in the new role, click a plus button. It POSTs to the AddRole route. How can I now update the model and update the grid?

From what I've seen, I need to run the insert, grab all the roles again, and update the grid in the "success" event. Is this true? Or is there a more conventional, MVC means to doing this via ASP.net? Obviously, I could go down the path of using Knockout or something to that extent, but I'm wondering if there is a means to updating the view this way.


Solution

  • Your POST method is attempting to redirect to another action method, but ajax calls do not redirect. Change you method to return the new roles Id value and return it to the view as json

    [HttpPost]
    [Route("addrole")]
    public async Task<ActionResult> AddRole(string description)
    {
      IdentityRole role = new IdentityRole();
      role.Name = description;
      var result = await RoleManager.CreateAsync(role);
      if (result.Succeeded)
      {
        return Json(role.Id);
      } else {
        return Json(null);
      }
    }
    

    Then modify your ajax to add the new role in the success callback based on the value of the textbox and the returned Id value

    var description = $('#add-role-text').val();
    var url = '@Url.Action("AddRole")';
    var table = $('#grid-basic');
    $.post(url, { description: description }, function(id) {
      if (!id) { 
        // oops 
        return;
      }
      var newRow = [{ role_id: id, description: description }];
      table.bootgrid("append", newRow);
    }).fail(function() {
      // oops - display error message?
    });