First of all, a bit of background - recently started my first asp.net core project, or it would more precise to say first dev project in like 10 years, so yeah, currently rate myself a newb in development.
So when I got the multi-tenancy, authentication, authorization done, I started to look for UI elements for my project, came across datatables, and was pretty sure that I would love to include this UI element in my project. Editing data grids is a must for me, so it was disappointing to find out that there is no libraries for asp.net core for Editor server-side. Although I haven't yet bought it, I decided to try to implement the server side myself. Long story short, 2 days later I have editable table, and I am willing to share my solution, as it could help someone else or me (by someone improving upon it). So here we go.
- Models
public class ProjectType
{
[Required]
public int Id { get; set; }
[Required]
public string ProjType { get; set; }
}
public class ProjectTypeDTable : ProjectType
{
public string DT_RowId { get; set; }
}
- Editor and datatable initialization
<script type="text/javascript">
$(document).ready(function () {
var editor = new $.fn.dataTable.Editor({
ajax: {
url: '/api/dtprojecttype',
data: function (d) {
return JSON.stringify(d);
},
contentType: "application/json"
},
table: '.projecttypes-table',
idSrc: 'id',
fields: [
{
name: "projType",
label: "Project Type: "
}
],
});
var generateProjectTypesTable =
$('.projecttypes-table').DataTable({
columns: [
{
data: "id",
searchable: false,
},
{ data : "projType" }
],
ordering: true,
paging : true,
pagingType : 'full_numbers',
pageLength : "25",
select : true,
dom: '<"html5buttons"B>lTfgitp',
buttons : [
{ extend: 'create', editor: editor },
{ extend: 'edit', editor: editor },
{ extend: 'remove', editor: editor },
{ extend: 'copy' }
]
});
//$('.projecttypes-table').on('click', 'tbody td', function () {
// editor.inline(this);
//});
});
</script>
- Server side api action
public async Task<IActionResult> Post([FromBody]JObject request)
{
//split incomming JSON object into action and data JTokens
var action = request.GetValue("action").ToString();
var data = request.GetValue("data");
IList<ProjectTypeDTable> testchangedobjects = new List<ProjectTypeDTable> { };
test
//define new list for changed objects
IList<ProjectTypeDTable> changedobjects = new List<ProjectTypeDTable> { };
//parse json to class objects
changedobjects = changedobjects.DTableEditParser(request, "Id", "Int");
//create empty List for response objects
IList<ProjectTypeDTable> responseobjects = new List<ProjectTypeDTable> { };
if (action == "create")
{
foreach (var x in changedobjects)
{
var changed = new ProjectType
{
ProjType = x.ProjType
};
changed = await _tenantdbrepo.AddProjectTypeAsync(changed);
responseobjects.Add(new ProjectTypeDTable { Id = changed.Id, ProjType = changed.ProjType, DT_RowId = "row_" + changed.Id.ToString() });
};
}
else if (action == "edit")
{
foreach (var x in changedobjects)
{
var changed = new ProjectType
{
Id = x.Id,
ProjType = x.ProjType
};
changed = await _tenantdbrepo.UpdateProjectTypeAsync(changed);
responseobjects.Add(new ProjectTypeDTable { Id = changed.Id, ProjType = changed.ProjType, DT_RowId = x.DT_RowId ?? "row_"+changed.Id });
};
}
else if (action == "remove")
{
foreach (var x in changedobjects)
{
var changed = new ProjectType
{
Id = x.Id,
ProjType = x.ProjType
};
await _tenantdbrepo.RemoveProjectTypeAsync(changed);
};
};
if (responseobjects.Any())
{
dynamic response = new
{
data = responseobjects
};
return Json(response);
}
else
{
dynamic response = new { };
return Json(response);
};
}
- My extension that parses the json to objects
public static class DatatablesEdit
{
public static IList<T> DTableEditParser<T>(this IList<T> source, JObject json, string id, string idtype)
{
//split incomming JSON object into action and data JTokens
var action = json.GetValue("action").ToString();
var data = json.GetValue("data");
IList<T> changedobjects = new List<T> { };
foreach (JProperty x in data)
{
//initialize empty object of class
T changedobject = (T)Activator.CreateInstance(typeof(T));
//set object's ID property to JSON objects Name
if (idtype =="int")
{
changedobject.GetType().GetProperty(id).SetValue(changedobject, Int32.Parse(x.Name.ToString()));
} else if (idtype == "string")
{
changedobject.GetType().GetProperty(id).SetValue(changedobject, x.Name.ToString());
}
//loop through each of JSON object sub properties, change the property name from camel case to pascal case and map to object's properties
foreach (JProperty y in x.Value)
{
string propertyname = char.ToUpper(y.Name[0]) + y.Name.Substring(1);
if (changedobject.GetType().GetProperty(propertyname).PropertyType.Name == "String")
{
changedobject.GetType().GetProperty(propertyname).SetValue(changedobject, y.Value.ToString());
}
else if (changedobject.GetType().GetProperty(propertyname).PropertyType.Name == "Integer")
{
changedobject.GetType().GetProperty(propertyname).SetValue(changedobject, Int32.Parse(y.Value.ToString()));
}
}
//add object to changed objects List
changedobjects.Add(changedobject);
}
return changedobjects;
}
}
I am sure that the code is far from optimal, but I am pretty proud of myself to get this working. Any improvements appreciated.