Search code examples
asp.netasp.net-mvckendo-uikendo-ui-grid

Kendo ui grid fails at canceling the inline edit on aspnet mvc


I have come across a frustrating issue lately. I'm using kendi ui Grid on asp.net mvc ... the problem I'm running into is when I switch grid editable mode on and add the edit command and model Id, everything seems to be working but there are issues. First it doesn't hit the edit action on the controller then if I cancel the edit, the row is going to disappear!

This is my model

public class ContactInformation
{
    [Key]
    [ScaffoldColumn(false)]
    public long ContactInfoId { get; set; }

    public string Position { get; set; }

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

    public string PhoneNumber { get; set; }

    public string CodeToPerson { get; set; }

    public string Fax { get; set; }

    public string CellPhoneNumber { get; set; }

    public string Email { get; set; }

    public virtual Client Client { get; set; }
}

This is the controller

public class ContactsController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET: dashboard/Contacts
    public ActionResult Default(string id)
    {
        if(id != null)
        {
            ViewBag.clientGuid = id;

            var model = db.Clients.SingleOrDefault(x=>x.ClientGuid == id);
            model.BillingAddresses = db.BillingAddresses.Where(x => x.Client.ClientId == model.ClientId).ToList();
            return View(model);
        }
        return View();
    }        

    public ActionResult Contacts_Read([DataSourceRequest]DataSourceRequest request, string id)
    {
        var contacts = (id != null) ?
                            db.ContactInfos.Where(x => x.Client.ClientGuid == id).ToList() :
                            db.ContactInfos.ToList();

        return Json(GetContacts(contacts).ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public JsonResult Contacts_Create([DataSourceRequest]DataSourceRequest request,ContactInformation model)
    {
        // Todo: save the model

        return Json(ModelState.ToDataSourceResult());
    }

    [HttpPost]
    public ActionResult Contacts_Update([DataSourceRequest]DataSourceRequest request, ContactInformation model)
    {
        if(model != null)
        {
            var contactToUpdate = db.ContactInfos.Find(model.ContactInfoId);
            contactToUpdate.Name = model.Name;
            contactToUpdate.Position = model.Position;
            contactToUpdate.PhoneNumber = model.PhoneNumber;
            contactToUpdate.CodeToPerson = model.CodeToPerson;
            contactToUpdate.CellPhoneNumber = model.CellPhoneNumber;
            contactToUpdate.Fax = model.Fax;
            contactToUpdate.Email = model.Email;
            contactToUpdate.Client = db.Clients.Find(model.Client.ClientId);

            db.SaveChanges();

        }

        return Json(ModelState.ToDataSourceResult());
    }

    public IEnumerable<ContactInformation> GetContacts(List<ContactInformation> contacts)
    {
        return contacts.Select(contactInfo => new ContactInformation
        {
            Position = contactInfo.Position,
            Name = contactInfo.Name,
            PhoneNumber = contactInfo.PhoneNumber,
            CodeToPerson = contactInfo.CodeToPerson,
            Fax = contactInfo.Fax,
            CellPhoneNumber = contactInfo.CellPhoneNumber,
            Email = contactInfo.Email,
            Client = new Client()
            {
                CompanyName = contactInfo.Client.CompanyName,
                IndustryCategory = contactInfo.Client.IndustryCategory,
                IndustrySubCategory = contactInfo.Client.IndustrySubCategory
            }
        });
    }
}

This is the view

 @(Html.Kendo().Grid<ContactInformation>().Name("Contacts")
        .Columns(
            columns.Bound(c => c.Client.IndustryCategory).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.Client.IndustrySubCategory).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.Name).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.Position).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.PhoneNumber).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.CodeToPerson).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.CellPhoneNumber).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.Fax).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Bound(c => c.Email).Filterable(ftb => ftb.Cell(cell => cell.Operator("contains").SuggestionOperator(FilterType.Contains)));
            columns.Command(command =>
            {
                command.Edit();                    
            }).Width(100);
        })
        .ToolBar(tools =>
        {
            tools.Excel();
        })
        .Excel(excel => excel
            .FileName("ContactsData.xlsx")
            .Filterable(true)
            .ProxyURL(Url.Action("Excel_Export_Save"))
        )
        .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
        .Pageable(pageable => pageable
                    .Refresh(true)
                    .PageSizes(true)
                    .ButtonCount(5))
        .Scrollable()
        .Sortable()
        .Groupable()
        .Events(events=>events.Cancel("error_handler"))
        .Editable(editable => editable.Mode(GridEditMode.InLine))
        .HtmlAttributes(new { style = "height:500px;" })
        .DataSource(dataSource => dataSource
            .Ajax()
            .Model(Model=> {
                Model.Id(c => c.ContactInfoId);
                Model.Field(c => c.Client.IndustryCategory).Editable(false);
                Model.Field(c => c.Client.IndustrySubCategory).Editable(false);
            })
            //.Create(create => create.Action("Contacts_Create", "Contacts"))
            .Read(read => read.Action("Contacts_Read", "Contacts", new { id = ViewBag.clientGuid }))
            .Update(update => update.Action("Contacts_Update", "Contacts", new { id = ViewBag.clientGuid }))
            .PageSize(20)
        )
        .ColumnMenu()
)



<script type="text/javascript">
function error_handler(e) {
    if (e.errors) {
        var message = "Errors:\n";
        $.each(e.errors, function (key, value) {
            if ('errors' in value) {
                $.each(value.errors, function() {
                    message += this + "\n";
                });
            }
        });
        alert(message);
    }
}
</script>

The interesting thing, there is another model called inquiry in the project that has grid the same as this one and it works quite fine. Actually, they are quite identical but I couldn't figure it out why this doesn't work like the other!


Solution

  • First thing I see here is that your method in controller is HttpPost but in the definition of update function (on Telerik grid) you didn't specify it. It means, that grid is trying to trigger default one - and it is HttpGet -> that's why update is not triggered.

    You need to define that update method is Post

    .Update(update => update.Action("Contacts_Update", "Contacts", new { id = ViewBag.clientGuid }).Type(HttpVerbs.Post))