I have tried several solutions found here and elsewhere on the web but I still can't get the server sent errors to properly display on the jqgrid edit form. I have put breakpoints in the afterSubmit method of the jqgrid but it's never hit. I have simplified it to just show an alert if the method is executed but nothing is working. What I end up with is the stacktrace displayed into the header of the edit form. What did I miss?
JQGrid Code
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$("#JQGrid1").jqGrid({
url: '@Url.Action("GetData", "InvoiceType")',
editurl: '@Url.Action("EditData", "InvoiceType")',
mtype: "GET",
datatype: "json",
page: 1,
colModel: [
{ editable: true, editoptions: { readonly: "readonly" }, key: true, width: 60, label: "Id", name: "Id", hidden: false },
{ editable: true, width: 250, label:"Name", name: "Name", hidden: false },
{ editable: true, editoptions: { readonly: "readonly" }, width: 175, label: "Date Created", name: "DateCreated", align: 'right', hidden: false, formatter: "date", formatoptions: { srcformat: "m/d/Y h:i:s A", newformat: "m/d/Y h:i:s A" } },
{ editable: true, editoptions: { readonly: "readonly" }, width: 175, label: "Date Updated", name: "DateUpdated", align: 'right', hidden: false, formatter: "date", formatoptions: { srcformat: "m/d/Y h:i:s A", newformat: "m/d/Y h:i:s A" } },
{ editable: true, editoptions: { readonly: "readonly" }, width: 200, label: "Created By", name: "UpdatedBy", hidden: false },
//{ editable: true, editoptions: { readonly: "readonly" }, width: 50, label: "Active", name: "Active", hidden: false },
{ editable: true, editoptions: { value: "1:0" }, edittype: "checkbox", width: 50, label: "Active", name: 'Active', index: 'Active', formatter: 'checkbox', align: 'center', stype: "select", searchoptions: { value: "1:Yes;0:No" } },
],
height: "350",
autowidth:true,
shrinkToFit: false,
caption: "Invoice Types",
rowNum: 10,
pager: "#JQGrid1_pager",
rowattr: function (rd) {
if (rd.Active === 'False') {
return { "class": "myAltRowClass" };
}
},
loadComplete: function () {
//alert("OK");
},
loadError: function(jqXHR, textStatus, errorThrown) {
alert('HTTP status code: ' + jqXHR.status + "\n" +
'textStatus: ' + textStatus + "\n" +
'errorThrown: ' + errorThrown);
alert('HTTP message body (jqXHR.responseText): ' + "\n" + jqXHR.responseText);
},
}).jqGrid('navGrid', '#JQGrid1_pager', { edit: true, add: true, del: true, search: false, view: true, refresh: true },
{
// edit options
editCaption: "The Edit Dialog",
recreateForm: true,
checkOnUpdate: true,
checkOnSubmit: true,
closeAfterEdit: true,
height: 'auto',
width:'auto',
errorTextFormat: function (response) {
return '<span class="ui-icon ui-icon-alert" ' +
'style="float:left; margin-right:.3em;"></span>' +
response.responseText;
},
afterSubmit: function (response) {
var myInfo = '<div class="ui-state-highlight ui-corner-all">' +
'<span class="ui-icon ui-icon-info" ' +
'style="float: left; margin-right: .3em;"></span>' +
response.responseText +
'</div>',
$infoTr = $("#TblGrid_" + $.jgrid.jqID(this.id) + ">tbody>tr.tinfo"),
$infoTd = $infoTr.children("td.topinfo");
$infoTd.html(myInfo);
$infoTr.show();
// display status message to 3 sec only
setTimeout(function () {
$infoTr.slideUp("slow");
}, 3000);
return [true, "", ""]; // response should be interpreted as successful
}
},
{
//add options
closeAfterAdd: true,
recreateForm: true,
height: 'auto',
width: 'auto',
errorTextFormat: function (data) {
return 'Error: ' + data.responseText
}
},
{
// del options
errorTextFormat: function (data) {
return 'Error: ' + data.responseText
}
},
{
//search
},
{
//view details form
height: 'auto',
width: '400',
});
});
</script>
Web API Controller Method Code
[ResponseType(typeof(HttpResponseMessage))]
[HttpPut]
public HttpResponseMessage Put(int id, [FromBody] InvoiceTypeModel item)
{
if (item == null)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read Invoice Type from body");
InvoiceType originalItem = db.InvoiceTypes.FirstOrDefault(x => x.Id == id);
if (originalItem == null || originalItem.Id != id)
{
item.Id = 0;
Post(item);
}
InvoiceType nameMatchItem = db.InvoiceTypes.FirstOrDefault(x => x.Name == item.Name);
if (nameMatchItem != null && nameMatchItem.Id != item.Id)
return Request.CreateErrorResponse(HttpStatusCode.Conflict, "You can't have more than one record with the same name");
if (ModelState.IsValid && id == item.Id)
{
try
{
item.Id = id;
ObjectHelper.CopyPropertyValues(item, originalItem);
db.InvoiceTypes.ApplyCurrentValues(originalItem);
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound, "Record not found");
}
catch (Exception ex)
{
string c = ex.Message;
}
return Request.CreateResponse(HttpStatusCode.OK, "Update Successful");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not save to the database.");
}
}
Here's the Web Page Controller Code
[HttpPost]
public ActionResult EditData(string oper, int? Id, string Name, DateTime? DateCreated, int? Active)
{
InvoiceTypeModel cn = new InvoiceTypeModel();
switch (oper)
{
case "add":
{
cn.Id = 0;
cn.Name = Name;
cn.DateCreated = DateTime.Now;
cn.UpdatedBy = User.Identity.Name;
cn.Active = true;
_invoiceTypeRepository.Create(cn);
return Content("true");
}
case "del":
{
_invoiceTypeRepository.Delete((int) Id);
return Content("true");
}
case "edit":
{
cn.Id = (int) Id;
cn.Name = Name;
cn.DateCreated = (DateTime) DateCreated;
cn.DateUpdated = DateTime.Now;
cn.UpdatedBy = User.Identity.Name;
cn.Active = Active == 1;
_invoiceTypeRepository.Upsert(cn);
return Content("true");
}
}
return Content("false");
}
Here's a partial screenshot of the edit form after it receives the error. It's the correct information, a 409 Conflict but the formatting is not happening properly.