Hi Everyone,
I've been on this now for days without solution but with Edward effort, the issue is almost close.
I'm trying to submit data i loaded into JQuery Datatables. Below is my complete code
This is Model Class
public class GradeStep : Base.Configurations
{
public int Id { get; set; }
[Required, StringLength(250), Display(Name = "Grade Name")]
public string GradeName { get; set; }
[Required, StringLength(100), Display(Name = "Step Name"), RegularExpression(RegularExpressionPatternForFields.Pattern, ErrorMessage = "Invalid Step Name. Please remove any special character, leading or trailing spaces, etc.")]
public string StepName { get; set; }
[NotMapped]
[Display(Name = "Grade Code"), RegularExpression(RegularExpressionPatternForFields.Pattern, ErrorMessage = "Invalid Grade Code. Please remove any special character, leading or trailing spaces, etc.")]
public string GradeCode { get; set; }
[NotMapped, Required, Display(Name = "Grade From"), RegularExpression(RegularExpressionPatternForFields.Pattern, ErrorMessage = "Invalid Grade From Value. Please remove any special character, leading or trailing spaces, etc.")]
public string GradeFrom { get; set; }
[NotMapped, Display(Name = "Grade To"), RegularExpression(RegularExpressionPatternForFields.Pattern, ErrorMessage = "Invalid Grade To Value. Please remove any special character, leading or trailing spaces, etc.")]
public string GradeTo { get; set; }
[NotMapped, Required, Display(Name = "No. Of Step"), RegularExpression(RegularExpressionPatternForFields.Pattern, ErrorMessage = "Invalid No. Of Step Value. Please remove any special character, leading or trailing spaces, etc.")]
public string NoOfStep { get; set; }
[Display(Name = "Paygroup")]
public int PaygroupId { get; set; }
[ForeignKey("PaygroupId")]
public Paygroup Paygroup { get; set; }
}This is my Repository Class
public class GradeStepRep : IGPay<GradeStep>
{
private readonly GPayContext context;
private readonly IGPay<AuditTrail> auditTrail;
private readonly AuditTrailRep auditTrailRep;
public GradeStepRep(GPayContext _context, IGPay<AuditTrail> _auditTrail, AuditTrailRep _auditTrailRep)
{
context = _context;
auditTrail = _auditTrail;
auditTrailRep = _auditTrailRep;
}
public async Task DeleteAsync(List<GradeStep> model, HttpContext httpContext = null)
{
try
{
string gradeStepName = string.Empty;
foreach (var deleteModel in model)
{
if (deleteModel.Checked)
{
var gradeStep = await context.GradeStep.FindAsync(deleteModel.Id);
if (gradeStep != null)
{
context.GradeStep.Remove(gradeStep);
gradeStepName += $"{deleteModel.GradeName}/{deleteModel.StepName},";
}
}
}
await context.SaveChangesAsync();
AuditTrail audit = new AuditTrail
{
Module = Module.Configurations,
SubModule = SubModule.GradeStep,
Operation = Operation.Delete,
NewValue = $"(Grade/Step-{gradeStepName})"
};
await auditTrail.AddAsync(audit, httpContext);
}
catch (Exception)
{ throw; }
}
public Task<List<GradeStep>> GetAsync(GradeStep model = null, HttpContext httpContext = null)
{
try
{
List<GradeStep> gradeStep = context.GradeStep.Include(pg => pg.Paygroup).Where(gdStep => model.Status.Contains(gdStep.Status)).OrderBy(gdStep => gdStep.Paygroup.PaygroupName)
.ThenBy(gdStep => gdStep.GradeName).ThenBy(gdStep => gdStep.StepName).ToList();
return Task.FromResult(gradeStep);
}
catch (Exception)
{ throw; }
}
}This is my Controller Class
public class GradeStepController : Controller
{
private readonly IGPay<GradeStep> gradeStep;
private readonly IGPay<Paygroup> paygroup;
public GradeStepController(IGPay<GradeStep> _gradeStep, IGPay<Paygroup> _paygroup)
{
gradeStep = _gradeStep;
paygroup = _paygroup;
}
[HttpGet, Route("[Action]"), Authorize(Policy = "GradeStepView")]
public IActionResult GradeStep() => View();
[HttpPost, Route("[Action]"), Authorize(Policy = "GradeStepView")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> GradeStep([FromBody]List<GradeStep> model, [FromQuery]Operation operation)
{
try
{
if (model.Any(gradeStepChecked => gradeStepChecked.Checked))
{
switch (operation)
{
case Operation.Delete:
await gradeStep.DeleteAsync(model, HttpContext);
break;
case Operation.Authorize:
model[0].Status = Status.B.ToString();
await gradeStep.UpdateAsync(model, HttpContext);
break;
case Operation.Approve:
model[0].Status = Status.A.ToString();
await gradeStep.UpdateAsync(model, HttpContext);
break;
case Operation.Reject:
model[0].Status = Status.R.ToString();
await gradeStep.UpdateAsync(model, HttpContext);
break;
}
}
else
{
return BadRequest("Please, Select GradeStep!");
}
}
catch (Exception ex)
{
return BadRequest(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
}
return View();
}
[IgnoreAntiforgeryToken]
public async Task<JsonResult> GradeStepJson()
{
List<GradeStep> gradeStepPartialApprovedList = new List<GradeStep>();
gradeStepPartialApprovedList = await LoadGradeStep(new GradeStep { Status = Status.A.ToString() });
var draw1 = HttpContext.Request.Form["draw"].FirstOrDefault();
var start = HttpContext.Request.Form["start"].FirstOrDefault();
var length = HttpContext.Request.Form["length"].FirstOrDefault();
var searchValue = HttpContext.Request.Form["search[value]"].FirstOrDefault();
int pageSize = length != null ? Convert.ToInt32(length) : 0;
int skip = start != null ? Convert.ToInt32(start) : 0;
int recordsTotal1 = gradeStepPartialApprovedList.Count();
if (!string.IsNullOrWhiteSpace(searchValue))
{
gradeStepPartialApprovedList = gradeStepPartialApprovedList.Where(gd => gd.Paygroup.PaygroupName.ToLower().Contains(searchValue.ToLower()) || gd.GradeName.ToLower().Contains(searchValue.ToLower()) || gd.StepName.ToLower().Contains(searchValue.ToLower())).ToList();
}
int filterTotal = gradeStepPartialApprovedList.Count();
var data1 = gradeStepPartialApprovedList.Skip(skip).Take(pageSize).ToList();
return Json(new { draw = draw1, recordsTotal = recordsTotal1, recordsFiltered = filterTotal, data = data1 });
}
}This is my View Page
@{
ViewData["Title"] = "GradeStep";
}
@section Header{
@ViewData["Title"]
}<div id="divGradeStepApproved" class="form-group"><form id="fmApprovedGradeStep" method="post" asp-controller="GradeStep" asp-action="GradeStep"><div asp-validation-summary="All" class="text-danger"></div><div class="card text-center"><div class="card-header text-muted"><p><b>Approved GradeStep</b></p></div><div class="card-body"><div class="form-group row"><label class="col-sm-2 col-form-label">Search</label><div class="col-sm-4 input-group"><div class="input-group-prepend"><span class="input-group-text fa fa-search"></span></div><input id="gradeStepApprovedSearch" type="text" class="form-control" placeholder="Search by Paygroup, Grade, Step" /></div></div><div class="form-group"><div class="table-responsive-sm"><table id="gradeStepApprovedTable" class="table table-striped table-bordered table-sm compact"><thead><tr><th scope="col" class="text-center"><div class="form-check"><input id="gradeStepApprovedCheckAll" type="checkbox" class="form-check-input" /><label class="form-check-label"></label></div></th><th scope="col" class="text-center"><label>Paygroup</label></th><th scope="col" class="text-center"><label>Grade</label></th><th scope="col" class="text-center"><label>Step</label></th><th scope="col" class="text-center"><label>Remarks</label></th><th scope="col" class="text-center"><label>Status</label></th><th scope="col"></th></tr></thead></table></div></div></div><div class="card-footer"><div class="btn-group-sm">
@if (await Context.IsUserInRoleAsync(User.Identity.Name, Role.GradeStepAdd.ToString()))
{<a id="btnGradeStepAdd" asp-controller="GradeStep" asp-action="GradeStepAddEdit" class="btn btn-outline-success"><span class="fa fa-plus"></span>
Add</a>
}
@if (await Context.IsUserInRoleAsync(User.Identity.Name, Role.GradeStepDelete.ToString()))
{<button id="btnGradeStepApproveDelete" type="button" class="btn btn-outline-success" data-loading-text="Deleting..." onclick="Delete('#fmApprovedGradeStep', '#btnGradeStepApproveDelete');"><span class="fa fa-trash"></span>
Delete</button>
}</div></div></div></form></div><script type="text/javascript">
function Delete(formId, btnId) {
if ($(formId).valid()) {
ClearValidationSummary();
if (confirm("Do you want to delete GradeStep(s)")) {
var btn = $(btnId);
var btnContent = $(btnId).html();
var table = $('#gradeStepApprovedTable').DataTable()
console.log(JSON.stringify(table.rows().data().toArray()));$.ajax({"method": "post","contentType": "application/json","data": JSON.stringify(table.rows().data().toArray()),"url": "@Url.Action("GradeStep", "GradeStep", new { operation = Operation.Delete })","beforeSend": function (jqXHR, settings) {
ButtonShowLoadingText(btn);
}
}).done(function (data, textStatus, jqXHR) {
SuccessAlert("GradeStep(s) deleted successfully.");
}).fail(function (jqXHR, textStatus, errorThrown) {
ErrorAlert(jqXHR.responseText);
}).always(function (jqXHR, textStatus) {
ButtonOffLoadingText(btn, btnContent);
});
}
}
}$(document).ready(function () {
var jTableFilter = @Configuration.GetSection("GPayCustomSettings").GetValue(typeof(string), "JTableFilter");
var dataTableGradeStepApproved = $("#gradeStepApprovedTable").DataTable({"ordering": false,"destroy": true,"pagingType": "full_numbers","lengthMenu": jTableFilter,"processing": true,"serverSide": true,"ajax": {"url": "@Url.Action("GradeStepJson", "GradeStep")","type": "post","dataType": "json"
},"columns": [
{"data": "checked", "name": "checked", "searchable": false, "render": function (data, type, row) {
return '<input type="checkbox" />';
} },
{ "data": "paygroup.paygroupName", "name": "paygroup.paygroupName", "searchable": true },
{ "data": "gradeName", "name":"gradeName", "searchable": true },
{ "data": "stepName", "name":"stepName", "searchable": true },
{ "data": "remarks", "name":"remarks", "searchable": false },
{"data": "status", "name": "status", "searchable": false, "render": function (data, type, row) {
switch (data.toUpperCase()) {
case "A":
return "Approved";
default:
return "Undefined";
}
}
},
{"data": "id", "name": "id", "searchable": false, "render": function (data, type, row) {
return '@if (await Context.IsUserInRoleAsync(User.Identity.Name, Role.GradeStepUpdate.ToString())) { <a href="@Url.Action("GradeStepAddEdit", "GradeStep")/'+ data +'" class="btn btn-outline-success btn-sm"><span class="fa fa-edit"></span>Edit</a> }';
} }
]
});$("#gradeStepApprovedSearch").bind("keyup search input paste cut", function () {
dataTableGradeStepApproved.search($(this).val()).draw();
});
});</script>Initially the data couldn't be loaded into Model but after i applied Edward modified Delete Function and GradeStep Action Method Parameter by including [FromBody] and [FromQuery] Model Binding, the data loaded into Model but there are two points here to resolve.
- I had to include [IgnoreAntiforgeryToken] attribute to GradeStep Action Method before the method gets called by Delete Function. Is there a way i can tackle this?
- If you notice, I render checkbox in first column. The issue here is, if i check the checkbox(es), it doesn't reflect in the model as true.
Thanks in advance.