I tried to write a lob application using ejs-grid (i.e. CRUD) operations with Razor Pages. It was not possible. I need help.
I have the following class/table:
public class PlannedRoute
{
public int PlannedRouteId { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public bool IsActive { get; set; }
public DateOnly NextPlannedDay { get; set; }
}
The following PlannedRouteUA.cshmtl:
@page
@model trackmate.web.Pages.CRUDs.PlannedRoutePages.PlannedRouteUAModel
@{
ViewData["Title"] = "Edit";
Layout = "~/Pages/CRUDs/Shared/_CrudLayout.cshtml";
}
<script>
function gridload() {
this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': document.querySelector('input[type="hidden"][name="__RequestVerificationToken"]').value }];
}
</script>
@{
string fullUrl = $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}";
}
@Html.AntiForgeryToken()
<div class="control-section">
<ejs-grid id="Grid" allowPaging="true" toolbar="@(new List<string>() { "Add", "Edit", "Delete","Update","Cancel" })" load="onLoad">
<e-data-manager url="@fullUrl?handler=UrlDatasource" adaptor="UrlAdaptor" insertUrl="@fullUrl?handler=Insert" updateUrl="@fullUrl?handler=Update" removeUrl="@fullUrl?handler=Delete"></e-data-manager>
<e-grid-editSettings allowAdding="true" allowDeleting="true" allowEditing="true" mode="Normal"></e-grid-editSettings>
<e-grid-pagesettings pageSize="5"></e-grid-pagesettings>
<e-grid-columns>
<e-grid-column field="PlannedRouteId" headerText="ID" validationRules="@(new { required=true})" isPrimaryKey="true" textAlign="Center" width="100"></e-grid-column>
<e-grid-column field="Name" headerText="Ονομασία" textAlign="Center" width="100"></e-grid-column>
<e-grid-column field="Description" headerText="Περιγραφή" textAlign="Center" width="100"></e-grid-column>
<e-grid-column field="IsActive" headerText="Ενεργό?" editType="booleanedit" displayAsCheckBox="true" type="boolean" width="100"></e-grid-column>
<e-grid-column field="NextPlannedDay" headerText="Next Planned Day" customFormat="@(new { type ="date", format="dd/MM/yyyy" })" type="date" editType="datepickeredit" width="160"></e-grid-column>
</e-grid-columns>
</ejs-grid>
</div>
<script>
function onLoad() {
this.dataSource.dataSource.headers = [{
'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val()}];
}
</script>
And the following: handlers:
public async Task<JsonResult> OnPostUpdateAsync()//[FromBody] ICRUDModel<PlannedRoute> value)
{
string body = await new StreamReader(Request.Body).ReadToEndAsync();
ICRUDModel<PlannedRoute>? account = Newtonsoft.Json.JsonConvert.DeserializeObject<ICRUDModel<PlannedRoute>>(body);
return new JsonResult("");
}
public async Task<JsonResult> OnPostUrlDatasourceAsync([FromBody] DataManagerRequest dm)
{
IEnumerable DataSource = await _context.PlannedRoutes
.ToListAsync();
DataOperations operation = new DataOperations();
if (dm.Search != null && dm.Search.Count > 0)
{
DataSource = operation.PerformSearching(DataSource, dm.Search); //Search
}
if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
{
DataSource = operation.PerformSorting(DataSource, dm.Sorted);
}
if (dm.Where != null && dm.Where.Count > 0) //Filtering
{
DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
}
int count = DataSource.Cast<PlannedRoute>().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
return dm.RequiresCounts ? new JsonResult(new { result = DataSource, count = count }) : new JsonResult(DataSource);
}
Main default handler (UrlDatasource) works fine. I tried the synchronous and asynchronous calls. Both are fine.
The biggest problem is with the Insert/Update/Delete.
In Delete and Update, the default arguments ([FromBody] ICRUDModel<PlannedRoute> value) are always null.
In Delete, the message having a "key" possibly raises an exception with (the default) System.Text.Json, although it is deserialized by Newtonsoft. That is the reason I commented out the code as it is suggested her(https://ej2aspnetcore.azurewebsites.net/aspnetcore/grid/urladaptor#/ ).
With my code and deserializing with newtonsoft, I managed to get the data.
In update though, there is a strange issue. Javascript send more fields that those required and crashes the JSON conversion.
This is the body from the httprequest:
{value: {plannedRouteId: 2, name: "πρώτη", description: "NULLδφγ", trackerIMEIId: 1,…},…}action: "update"key: 2keyColumn: "PlannedRouteId"value: {plannedRouteId: 2, name: "πρώτη", description: "NULLδφγ", trackerIMEIId: 1,…}Description: "NULLδφγ"IsActive: trueName: "πρώτη"NextPlannedDay: "2024-09-18T21:00:00.000Z"PlannedRouteId: 2defaultBus: {id: 1, description: "Το καινούριο MErcedes", plate: "ZZY354", firstDate: "2024-09-01",…}defaultBusId: 1defaultEscort: {id: 2, soft1Id: "90", name: "ΓΕΩΡΓΙΑ", isActive: true}defaultEscortId: 2description: "NULLδφγ"encodedRouteJSON: " "friday: trueisActive: truemaxDurationMinutes: 120monday: truename: "πρώτη"nextPlannedDay: "0001-01-01"plannedRouteId: 2recurring: truerouteOrderedTargets: []startTime: "07:30:00"thursday: truetrackerIMEI: {trackerIMEIId: 1, imei: 867255079789956, lastLat: 0, lastLon: 0,…}trackerIMEIId: 1tuesday: truewednesday: trueFrom the program in debugging, I have only one record and tried to "edit" (as it is shown on the image at the end). In "edit" I only corrected the field "NextPlannedDay". It was a default 1/1/1 and I changed it to 19/9/2024. BUT:
All htese additional fields crash the deserializers.
Here you can see that I selected 19/9, but inside the request body I have 18/9
I had solved the "strange" date issue.
All ajax communications are in UTC time.
I enter i.e. 26/9/2024 in the ui. I enter only the date and thus hour-minutes-seconds are defaulted to zero.
At the point ajax submits. it translates from local timezone (greece is UTC+3) to UTC, i.e. minus three hours: 25/9/2024 21:00::00.
Before storing to database, I should transform date (PlannedDate.ToLocalTime()), but for the ajax response I should leave it as it is in UTC and it is again correctly displayed....
The strange change of capital to small letters have an obvious workaround..... I just change naming conventions from Pascal to camel (i.e. the first letter is small and not capital).
Not the best solutions.....
For example, I tried to localize the asp.net ej syncfusion core, but this does not affect the transfer of the dates. Everything is tranformed to UTC.
Hi Nikos,
Greetings from Syncfusion support.
Upon reviewing your query, we have identified that you are facing issues with handling CRUD actions in the Syncfusion Grid while using UrlAdaptor.
Query 1 : “The strange change of capital to small letters have an obvious workaround..... I just change naming conventions from Pascal to camel (i.e. the first letter is small and not capital).”
By default, the JSON data returned from the backend is in camelCase format, hence the field names in the Grid also change to camelCase. To address this issue, you can use the DefaultContractResolver in the program.cs file. We have included this solution in the attached sample and have detailed it in our documentation. Please refer to the provided code example, sample, and documentation for further details.
|
Program.cs
var builder = WebApplication.CreateBuilder(args); builder.Services.AddMvc().AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver(); }); builder.Services.AddControllers();
|
Documentation Link: Troubleshoot-grid-render-rows-without-data
Query 2: “ I tried to localize the asp.net ej syncfusion core, but this does not affect the transfer of the dates. Everything is transformed to UTC”.
By default, when using remote data, the server returns the time in UTC, which is then converted to local time and displayed in the Grid. To address this conversion issue, you can set the `serverTimezoneOffset` property in the `DataUtil` class, adjusting the offset according to your requirements. Please refer to the following code example where we set the `serverTimezoneOffset` value to the local time zone offset. Additional information on managing CRUD operations with URL data and handling different time zone offsets can be found in the attached sample and code example.
|
Index.cshtml
function onLoad() { this.dataSource.dataSource.headers = [{ 'XSRF-TOKEN': $("input:hidden[name='__RequestVerificationToken']").val() }]; // Getting the local time offset and assinging it to the serverTimezoneOffset ej.data.DataUtil.serverTimezoneOffset = new Date().getTimezoneOffset() / 60; }
|
Sample: Please find in the attachment.
If you need any other assistance or have additional questions, please feel free to contact us.
Regards
Aishwarya R