I am using the igGrid using the Grid Model approach. After Updating/Editing the grid post to an MVC controller. I would like an example how to handle Server Side errors and displaying the error to the returned View.
Thanks
Hello Eric,
Thank you for posting in our forum.
There are several different approaches that might be applicable, so I would appreciate some additional information with regard to your scenario:
Providing me those details would be greatly appreciated as it would allow me to get a better idea of the requirements you have, as well as the specifics of your web application.
I look forward to your reply.
Thanks Vasil,
Here is where I'm at so far.
I can get notification of server-error back from the request now. But, I want to be able to display the message; either as a modal or (as a ModelState error does) embedded in the view. If Unsuccessful, then display the error and scroll the grid back to the top, leaving changed data intact. If Successful, redirect to another view.
View.cshtml
@(Html.Infragistics().Grid(Model.PayIncreasePrevi <div class="row content-footer"> <div class="col-xs-12"> <ul class="pager pull-right"> <li> <button id="saveChanges" type="submit" class="btn btn-primary" value="Save">Perform Pay Increase</button> </li> </ul> </div> </div> @section Scripts{ <script type="text/javascript"> (function ($) { $(function () { $("#saveChanges").bind({ click: function (e) { $("#PayIncreasePreview").igGrid("saveChanges", function(result) { console.log(result); }); return false; } }); }); })(jQuery); </script> }
Controller.cs
[HttpGet] public ActionResult IncrementalPayIncreasePreview() { var model = _modelBuilder.BuildIncrementalPayIncreasePreviewModel(this.CurrentUser.CompanyID, this.CurrentUser.UserID); model.PayIncreasePreviewItems = GetPayIncreasePreviewGridModel(); return this.View("IncrementalPayIncreasePreview", model); } [HttpPost] public ActionResult IncrementalPayIncreasePreview(IncrementalPayIncreasePreviewModel model) { var defaultModel = _modelBuilder.BuildIncrementalPayIncreasePreviewModel(this.CurrentUser.CompanyID, this.CurrentUser.UserID); return this.View("IncrementalPayIncreasePreview", defaultModel); } private GridModel GetPayIncreasePreviewGridModel() { //define PayGrade layout GridModel payIncreasePreviewLayout = new GridModel(); payIncreasePreviewLayout.ID = "PayIncreasePreview"; payIncreasePreviewLayout.PrimaryKey = "SystemAssignedPersonID"; payIncreasePreviewLayout.Width = "100%"; //payIncreasePreviewLayout.AutoGenerateLayouts = false; //payIncreasePreviewLayout.AutoGenerateColumns = false; payIncreasePreviewLayout.AutofitLastColumn = true; payIncreasePreviewLayout.RenderCheckboxes = true; payIncreasePreviewLayout.EnableResizeContainerCheck = true; payIncreasePreviewLayout.AnimationDuration = 100; payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "CompanyID", HeaderText = "Company ID", HeaderCssClass = "columnheader", DataType = "string", Width = "100%", Hidden = true }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "CompanyName", HeaderText = "Company Name", DataType = "string", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "SystemAssignedPersonID", HeaderText = "SystemAssignedPersonID", DataType = "number", Width = "100%", Hidden = true }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "UserAssignedEmployeeID", HeaderText = "Employee ID", DataType = "string", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "EmployeeName", HeaderText = "Employee Name", DataType = "string", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "PayGradeID", HeaderText = "Pay Grade ID", DataType = "string", Width = "100%", Hidden = true }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "PayGradeDescription", HeaderText = "Pay Grade", DataType = "string", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "CurrentPayRateHourly", HeaderText = "Current Pay Rate Hourly", DataType = "number", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "NewPayRateHourly", HeaderText = "New Pay Rate Hourly", DataType = "number", Width = "100%" }); payIncreasePreviewLayout.Columns.Add(new GridColumn() { Key = "IsSelected", HeaderText = "Apply Pay Increase", DataType = "bool", Width = "100%" }); payIncreasePreviewLayout.UpdateUrl = Url.Action("PerformPayIncrease", "MassGlobalUpdate"); //data source payIncreasePreviewLayout.DataSource = GetPayIncreasePreview().AsQueryable(); //features //sorting GridSorting sorting = new GridSorting(); sorting.Type = OpType.Local; payIncreasePreviewLayout.Features.Add(sorting); //updating GridUpdating updatingPayIncrease = new GridUpdating(); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "CompanyName", ReadOnly = true }); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "UserAssignedEmployeeID", ReadOnly = true }); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "EmployeeName", ReadOnly = true }); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "PayGradeDescription", ReadOnly = true }); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "CurrentPayRateHourly", ReadOnly = true }); updatingPayIncrease.ColumnSettings.Add(new ColumnUpdatingSetting() { ColumnKey = "NewPayRateHourly", EditorType = ColumnEditorType.Currency }); updatingPayIncrease.EditMode = GridEditMode.Row; updatingPayIncrease.EnableAddRow = false; updatingPayIncrease.EnableDeleteRow = false; payIncreasePreviewLayout.Features.Add(updatingPayIncrease); //resizing GridResizing resizing = new GridResizing() { AllowDoubleClickToResize = true }; payIncreasePreviewLayout.Features.Add(resizing); //responsive GridResponsive responsive = new GridResponsive() { ForceResponsiveGridWidth = true }; payIncreasePreviewLayout.Features.Add(resizing); ////moving //GridColumnMoving columnMoving = new GridColumnMoving(); //payIncreasePreviewLayout.Features.Add(columnMoving); return payIncreasePreviewLayout; } private List<PayIncreasePreviewItem> GetPayIncreasePreview() { var employeesDueForIncrease = _employeeService.GetIncrementalPayIncreaseEmployees(this.CurrentUser.CompanyID, this.CurrentUser.UserID); return employeesDueForIncrease; } public ActionResult PerformPayIncrease() { JsonResult result = new JsonResult(); Dictionary<string, bool> response = new Dictionary<string, bool>(); GridModel gridModel = new GridModel(); List<Transaction<PayIncreasePreviewItem>> exportFileTransactions = gridModel.LoadTransactions<PayIncreasePreviewItem>(HttpContext.Request.Form["ig_transactions"]); var payInfos = new List<PayInfo>(); foreach (Transaction<PayIncreasePreviewItem> t in exportFileTransactions) { if (t.type == "row") { var oPayInfo = _employeeService.GetPayInfos(this.CurrentUser.CompanyID, this.CurrentUser.UserID, t.row.SystemAssignedPersonID).OrderByDescending(x => x.PayChangeEffectiveDate).FirstOrDefault(); var payInfo = new PayInfo() { SystemAssignedPersonID = oPayInfo.SystemAssignedPersonID, CompanyID = oPayInfo.CompanyID, PayChangeEffectiveDate = DateTime.Now, PayChangeReasonID = "INCREMENT", PayRateHourly = oPayInfo.PayRateHourly + t.row.NewPayRateHourly, PayPeriodSalary = t.row.NewPayRateHourly * oPayInfo.StandardHoursPerPayPeriod, //AnnualSalary = (t.row.NewPayRateHourly * oPayInfo.StandardHoursPerPayPeriod) * Convert.ToDecimal(oPayInfo.PayFrequencyID), //need pay frequency weeks }; payInfos.Add(payInfo); } //execute update try { _employeeService.UpdateIncrementalPayIncreaseEmployees(this.CurrentUser.CompanyID, this.CurrentUser.UserID, payInfos); } catch { //response.Add("Success", true); //result.Data = response; //return result; } } response.Add("Success", true); result.Data = response; return result; }
The grid API provides the scrollContainer method which would give you the scroll container – it would allow you set the scrollTop to zero and scroll the grid to the top when there is an error – that is exactly what these two lines of the snippet below do:
let container = $('#grid').igGrid('scrollContainer')[0]
container.scrollTop = 0;
Setting the window.location.href to the according URL would allow you to redirect to another page if the server response is successful:
window.location.href = "">https://www.someotherurl.com"
You could then use success and error callback functions, which the “saveChanges” method would execute when the server responds back to the client. In case your popup has an id of “message”, the code might look like this one:
$("#grid").igGrid("saveChanges", function (data) { window.location.href = " https://www.someotherurl.com " }, function(jqXHR, textStatus, errorThrown) { $("#message").text("An error occurred while saving the changes. Error details: " + textStatus).fadeIn(3000).fadeOut(5000); let container = $('#grid').igGrid('scrollContainer')[0] container.scrollTop = 0; });
Please let me know if you have some additional questions regarding this matter.
Vasil,
A couple more questions..
try { //DO Something } catch (Exception ex) { response.Add(ex.ToString(), true); result.Data = response; return result; } response.Add("Success", true); result.Data = response; return result;
I this code I am trying to return the Exception message. This doesn't seem to work. I am obviously missing something. How does the igGrid take in a custom error message? What I receive back, with the following code is this...
$("#saveChanges").bind({ click: function (e) { $("#PayIncreasePreview").igGrid("saveChanges", function (data) { window.location.href = '@Url.Action("Index", "MassGlobalUpdate")'; }, function (jqXHR, textStatus, errorThrown) { console.log(textStatus); console.log(errorThrown); }); return false; } });
Console:
Saving changes was not successful. Server did not return Success object or returned Success:false
What is the best way to send the Exception message back to the client. And could you explain or point me to documentation why the JSON response should be a dictionary<string,bool> and what it means to send back true and false?
The reason a dictionary<string, bool> is used, is because “Success: true” has to be added to the response to the client – the igGrid relies on it in order to execute the “success” callback of the “saveChanges” method. Without this property, the error callback (if you have such) would be executed every time.
This help topic provides a more detailed code sample and explanation.
I have attached a small MVC sample that has a simple igGrid, which sends a request to the server by calling “saveChanges” when a "save" button is pressed. Try adding or editing a row and once you press the button, the “success” handler would be executed. If you try to delete a row, the server would not allow it and would return an error message, which would be shown to the client.
MVCServerReponses.zip
Let me know if you need some additional information with regard to this topic.
Thank you very much for your help and clarification.
Eric
I am glad that you find my answer helpful.
Feel free to contact me if you have some further questions regarding this scenario.