How to save grid data temporarily in ASP.NET Razor?

1 Answer 185 Views
Grid
Janko
Top achievements
Rank 1
Iron
Iron
Janko asked on 30 Aug 2023, 02:04 PM

I have a grid which is a part of bigger form. I want to be able to do all sorts of data manipulation without saving it immediately. When saving form, I need to save data in a grid.

I'm experiencing a problem when editing a row in InLine mode. When I click on "edit", then "cancel", the row disappears from the grid depending on how I load data into the grid.

If Read method looks like this, than canceling edit works good but I'm not able to save data temporarily.

public JsonResult OnPostRead([DataSourceRequest] DataSourceRequest request)
        {
            ToDestinations = _entities.ToDestinations.ToList();
            //var data = HttpContext.Session.Get("ToDestinationsData");
            //if (data != null)
            //{
            //    ToDestinations = JsonConvert.DeserializeObject<List<ToDestination>>(Encoding.UTF8.GetString(data));
            //}

            return new JsonResult(ToDestinations.ToDataSourceResult(request));
        }

On the other hand, if Read method looks like below, every row that I'm doing "edit" => "cancel" disappears. (This was a start to making grid data persistent while doing all kinds of data manipulation in a grid.)

public JsonResult OnPostRead([DataSourceRequest] DataSourceRequest request)
        {
            //ToDestinations = _entities.ToDestinations.ToList();
            var data = HttpContext.Session.Get("ToDestinationsData");
            if (data != null)
            {
                ToDestinations = JsonConvert.DeserializeObject<List<ToDestination>>(Encoding.UTF8.GetString(data));
            }

            return new JsonResult(ToDestinations.ToDataSourceResult(request));
        }

This is my grid.

@(Html.Kendo().Grid<ToDestination>()
            .Name("grid")
            .Columns(columns =>
            {
                columns.ForeignKey(c => c.TravelTypeId, ds => ds.Read(read => read.Url(Url.Page("Create", "TravelTypes"))), "TravelTypeId", "TravelTypeName").Title("Vrsta putovanja");

                columns.ForeignKey(c => c.CountryId, ds => ds.Read(read => read.Url(Url.Page("Create", "Countries"))), "CountryId", "CountryName", true).Title("Država")
                .EditorTemplateName("CountryEditor"); // Specify a custom editor template for the Country dropdown.

                columns.ForeignKey(c => c.PlaceId, ds => ds.Read(read => read.Url(Url.Page("Create", "Places"))), "PlaceId", "PlaceName", true).Title("Mjesto")
                .EditorTemplateName("PlaceEditor"); // Specify a custom editor template for the Place dropdown.

                columns.ForeignKey(c => c.CenterId, ds => ds.Read(read => read.Url(Url.Page("Create", "Centers"))), "CenterId", "CenterName", true).Title("Centar")
                .EditorTemplateName("CenterEditor"); // Specify a custom editor template for the Center dropdown.

                columns.Command(command => { command.Edit(); command.Destroy(); }).Width(250);
            })
            .ToolBar(toolbar => toolbar.Create())
            .Editable(editable => editable.Mode(GridEditMode.InLine))
            .Pageable()
            .Sortable()
            .Scrollable()
            .DataSource(ds => ds.Ajax()
            .Create(c => c.Url("/TravelOrders/Create?handler=Create").Data("forgeryToken"))
            .Read(r => r.Url("/TravelOrders/Create?handler=Read").Data("forgeryToken"))
            .Update(u => u.Url("/TravelOrders/Create?handler=Update").Data("forgeryToken"))
            .Destroy(d => d.Url("/TravelOrders/Create?handler=Destroy").Data("forgeryToken"))
            .Model(m =>
            {
                m.Id(id => id.ToDestinationId);
            })
            ))

I hope what I wrote makes sense.

What is the best practice to achieve saving grid data temporarily without "edit" => "cancel" bug appearing?

1 Answer, 1 is accepted

Sort by
0
Stoyan
Telerik team
answered on 04 Sep 2023, 02:21 PM

Hello Janko,

I have tried to replicate the issue locally but I have found out that editing a row and then canceling the changes doesn't trigger a Read request being sent to the server.

This can be seen in the Network tab of the Grid InLine Editing Demo as well as in this Telerik REPL example which includes the use of ForeignKey columns.

The findings above lead me to suspect the reported issue arises as a result of some additional configuration present on your side. Please consider sharing the full configuration of the Grid and the form it is embedded in to enable me to investigate further.

Ideally, an isolated sample project that uses dummy data and showcases the scenario observed on your side will likely lead to a faster research and possible resolution of the issue.

Thank you for your consideration in advance.

Regards,
Stoyan
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages. If you're new to the Telerik family, be sure to check out our getting started resources, as well as the only REPL playground for creating, saving, running, and sharing server-side code.
Janko
Top achievements
Rank 1
Iron
Iron
commented on 06 Sep 2023, 10:26 AM | edited

Thank you for you answer Stoyan.

I've made a sample project that simulates this behavior (add new => save, then edit => cancel, row disappearing). My actual project is much more complex, but I think this sample will show you what is happening.

Stoyan
Telerik team
commented on 08 Sep 2023, 04:40 PM

Hello Janko,

Thank you for taking the

I have found that the initial entry disappears because the field specified for an Id isn't configured. Therefore the Id of that row has its default value set. Rows with default Ids are treated as newly created by the Grid. When the user clicks 'Cancel' the expected behavior is for new rows that aren't saved to be deleted.

The behavior can be mended by setting a value for the ToDestinationsId field in the OnGet function's declaration:

public void OnGet()
{
            ...
            ToDestinations = new List<ToDestination>{ new ToDestination { ToDestinationId=1, DestinationId = 1, CenterId = 1, PlaceId = 1, CountryId = 1, TravelTypeId = 1 }};
}

In regard to the newly created items - it appears they aren't saved correctly because server-side errors occur:

For this reason I have added an error_handler for the Error Event of the DataSource attached to the Grid. This allows you to display server-side errors.

.Events(e => e.Error("error_handler"))

    function error_handler(e) {
        if (e.errors) {
            var message = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            alert(message);
        }
    }

Fixing those errors will result in the proper saving of the new row entries in the Grid. Saved rows won't disappear when their editing is canceled.

For your convenience I am attaching the modified project which incorporates the code in the snippets above.

Sincerely,

Stoyan

 

Janko
Top achievements
Rank 1
Iron
Iron
commented on 11 Sep 2023, 09:10 AM

Thank you for explaining why the error occurs.

This behavior is very odd to me. Basically, all the fields on the form are required, no matter if they are connected to data in grid or not. Even when I provide those values I get the same errors (that the fields are required).

Is there a way to work around this? I can use temp table in database, but I think I shouldn't resort to that.

Stoyan
Telerik team
commented on 14 Sep 2023, 08:55 AM | edited

Hi Janko,

The reported behavior seems like a validation issue. Such issues usually stem either from the Model class configuration at the backend or by the validation logic applied in the Controller.

As a first step in the investigation I recommend you to try removing any [Required] DataAnnotations in the ToDestination class's properties.

Secondly, I recommend clarifying the server validation process and that errors aren't thrown unnecessarily during the validation.

Give these suggestions a try and let me know of the results.

Janko
Top achievements
Rank 1
Iron
Iron
commented on 15 Sep 2023, 12:35 PM

Putting ? next to objects and variables in models solves: field is required "error".

What I found out is that the new row only stays in grid when the row gets saved to database.

So what would be the recommended solution for scenario when I need to have data in grid temporarily and saving to database only when the form is submitted?

I'm thinking I should save data to temp table and then handle data manipulation on form submission / cancellation.

Initially, my idea was to handle data in a list of objects, then save / discard on submit / cancel, but right now I don't know how that would work.

What would be the best way to approach this?

Stoyan
Telerik team
commented on 20 Sep 2023, 08:45 AM

Hi Janko,

To achieve storing the data temporarily and then when certain criteria are met save it into a database I recommend utilizing Caching on the server-side.

For an in-depth guide on the use of server caching refer to the official Cache in-memory in ASP.NET Core documentation.

Moreover this StackOverflow thread might be helpful as well - Storing data temporarily in an ASP.NET Core application.

I hope the resources are useful as further customizations at the server-side run outside of the scope of the product.

If you need additional assistance in the configuration of the server-side I recommend our Professional Services.

 

Tags
Grid
Asked by
Janko
Top achievements
Rank 1
Iron
Iron
Answers by
Stoyan
Telerik team
Share this question
or