FileManager - capture server command response

1 Answer 25 Views
FileManager
Richard
Top achievements
Rank 4
Bronze
Bronze
Iron
Richard asked on 27 Aug 2025, 02:16 PM

Good afternoon,

I have a FileManager that I want to perform server-side checks when directories or files are renamed or deleted. For instance, the directory has files that must be kept.

I was hoping to use the command event:

command - API Reference - Kendo UI FileManager - Kendo UI for jQuery

Which mentions:

  • Fired when server command is executed (copy, move, delete or rename).
  • The event is useful to get feedback when server commands has failed or succeeded and take additional actions based on the status.

How, in my delete or update server methods, do I force an e.status of fail, and e.response text explaining why the delete or update was rejected, so I can handle that in the client Command event?

I can see that I could throw an error and then capture that in the Error event, but is it possible to do similar with the Command event?  The scenario I'm describing isn't really an error, just some validation that failed.

Kind regards,

Richard

1 Answer, 1 is accepted

Sort by
0
Accepted
Anton Mironov
Telerik team
answered on 01 Sep 2025, 05:31 AM

Hello Richard,

Thank you for the details provided.

You can handle server-side validation failures in the FileManager's Command event by customizing the server response in your delete or update methods. This approach allows you to communicate validation issues (such as protected files in a directory) to the client without triggering the Error event, since these are not actual errors but business rule validations.

How to return a custom response from the server:

  • In your server-side action (for delete, rename, etc.), return a JSON object with a status property (e.g., "fail") and a message describing the validation issue.

Example server-side code (C#):

return Json(new {
    status = "fail",
    message = "Cannot delete directory: contains files that must be kept."
});

Handling the response in the client Command event:

  • In your FileManager initialization, use the command event to check the response status and display the validation message.

Example client-side code:

$("#filemanager").kendoFileManager({
    // ... other configuration ...
    command: function(e) {
        if (e.status === "fail") {
            alert(e.response.message); // Show the validation failure to the user
            // Optionally, prevent further actions or update UI as needed
        }
        // Handle successful operations as usual
    }
});

Summary:

  • This method allows you to treat validation failures separately from actual errors, using the Command event for feedback.
  • You do not need to throw exceptions or use the Error event for validation logic.

For more details, refer to the FileManager Command event documentation:

I hope this information helps.

 

    Kind Regards,
    Anton Mironov
    Progress Telerik

    Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    commented on 01 Sep 2025, 10:02 AM

    Hi Anton,

    Many thanks for your reply.

    I had already tried something similar, which didn't seem to work.  I've now implemented your suggestion and it still doesn't appear to accept the status and message I'm sending.

    Here's how I've got it set up.

    Client-side code:

       @(Html.Kendo().FileManager().Name("filemanager")
           .DataSource(ds =>
           {
               ds.Read(operation => operation
                   .Type(HttpVerbs.Post)
                   .Action("Read", "FileManager")
                   .Data("getEnvironment")
               );
               ds.Destroy(operation => operation
                   .Type(HttpVerbs.Post)
                   .Action("Destroy", "FileManager")
                   .Data("sendingAdditionalParameter")
               );
               ds.Create(operation => operation
                   .Type(HttpVerbs.Post)
                   .Action("Create", "FileManager")
                   .Data("sendingAdditionalParameter")
               );
               ds.Update(operation => operation
                   .Type(HttpVerbs.Post)
                   .Action("Update", "FileManager")
                   .Data("sendingAdditionalParameter")
               );
           })
           .Toolbar(tb => tb.Items(items =>
           {
               items.Add("createFolder");
               items.Add("sortDirection");
               items.Add("sortField");
               items.Add("changeView");
               items.Add("spacer");
               items.Add("details");
               items.Add("search");
           }))
           .ContextMenu(context => context.Items(items =>
           {
               items.Add("rename");
               items.Add("delete");
           }))
           .Events(events => events
               .Command("onCommand")
               .Error("onError")
           )
       )

    function onCommand(e) { console.log("Command " + e.action + " = item: " + e.data.item.path + "; status: " + e.status); if (e.status === "fail") { e.sender.refresh(); var respsonse = e.response.message; if (response) { $("#error-message").html(response + "<br /><br />"); } } }

    Server-side code (C#):

            [ValidateAntiForgeryToken]
            public virtual async Task<ActionResult> DestroyAsync(FileModel entry, int environmentId)
            {
                if (environmentId > 0)
                {
                    var flag = true;
                    string responseText = string.Empty;
    
                    // Get list of folders mapped in the selected Environment
                    var folders = GetFolders(environmentId);
    
                    var path = NormalizePath(entry.Path);
    
                    if (!string.IsNullOrEmpty(path))
                    {
                        if (entry.IsDirectory)
                        {
                            // Check for mapping in db
                            var folder = folders.Any(l => l.Location == entry.Path);
    
                            if (folder)
                            {
                                flag = false;
                                responseText = "This folder is mapped in the database and cannot be deleted.";
                            }
                            else
                            {
                                DeleteDirectory(path);
                            }
                        }
                        else
                        {
                            DeleteFile(path);
                        }
                    }
    
                    if (!flag)
                    {
                        return Json(new { status = "fail", message = responseText });
                    }
                }
    
                return Json(Array.Empty<object>());
            }

    This is the outcome shown in the console:

    Is there something obvious that I'm missing?

    Kind regards,

    Richard

    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    commented on 03 Sep 2025, 01:45 PM

    Hi Anton,

    As a quick follow up, the response in the client Command event is showing as undefined:

    Even though the server response for the Destroy POST is showing the correct Json returned:

    Kind regards,

    Richard

    Anton Mironov
    Telerik team
    commented on 04 Sep 2025, 06:33 AM

    Hello Richard,

    Thank you for the kind words and the additional details provided.

    The issue is that the FileManager expects the server response for its CRUD operations (such as Destroy) to be in a specific format—typically an array of objects, not a plain object. If you return a plain object, the response will not be parsed as expected and e.response will be undefined in your Command event.

    How to Fix the Response Format

    Server-side:
    Change your response for validation failures from a plain object to an array containing your object.
    Example:

    return Json(new[] { new { status = "fail", message = responseText } });

    For successful operations, you can continue returning an empty array:

    return Json(Array.Empty<object>());
    Client-side Handling in the Command Event

    Since the response is now an array, access the first element to get your custom status and message:
    function onCommand(e) {
        var response = e.response && e.response[0]; // Access the first item in the array
        console.log("Full response:", e.response);   // Debug: see the actual response
    
        if (response && response.status === "fail") {
            e.sender.refresh();
            if (response.message) {
                $("#error-message").html(response.message + "<br /><br />");
            }
        }
    }
    Give a try to this approach and if additional assistance is needed - send me a runnable sample of your application, and I will try my best to achieve the desired behavior.

    Best Regards,
    Anton Mironov

    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    commented on 04 Sep 2025, 12:39 PM

    Hi Anton,

    Many thanks for your reply and explanation.

    I've implemented your suggestion and I'm still seeing the same result - e.response is undefined:

    However, the response for the Destroy operation is now showing as an array:

    The code I'm running is similar to the demo, albeit I'm passing a parameter environmentId so that the server side code knows where to look for the folders/files.  The FileManager display is based on an environment chosen from a dropdown list. I'm just returning a custom response from the Destroy operation.

    I'm running Telerik UI for ASP.NET Core 2024 Q3

    Kind regards,

    Richard

    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    commented on 05 Sep 2025, 01:44 PM

    Hi Anton,

    I've upgraded to Telerik UI for ASP.NET Core 2025 Q3.

    I've built a simple app which is based on the demo https://demos.telerik.com/aspnet-core/filemanager but has the OnCommand(e) client event, and the following amendment to the Destroy server action:

            public virtual ActionResult Destroy(FileManagerEntry entry)
            {
                ICollection<FileManagerEntry> sessionDir = HttpContext.Session.GetObjectFromJson<ICollection<FileManagerEntry>>(SessionDirectory);
                var path = Path.Combine(ContentPath, NormalizePath(entry.Path));
                var currentEntry = sessionDir.FirstOrDefault(x => x.Path == path);
    
                if (currentEntry != null)
                {
                    var response = new[]
                    {
                        new { status = "fail", message = "This folder is mapped in the database and cannot be deleted." }
                    };
    
                    return Json(response);
                }
    
                throw new Exception("File Not Found");
            }

    This is also giving me the same result i.e. e.response is undefined.

    Unsurprisingly, it behaves similarly for the Rename/Update action.

    Kind regards,

    Richard

    Anton Mironov
    Telerik team
    commented on 09 Sep 2025, 10:24 AM

    Hi Richard,

    Thank you for the additional details provided.

    I decided to take a step back and prepare a sample project for the case with the code from 1 September.

    There is actually a typo in the "response" - one additional "s":

      function onCommand(e) {
            console.log("Command " + e.action + " = item: " + e.data.item.path + "; status: " + e.status);
    
            if (e.status === "fail") {
                e.sender.refresh();
                var respsonse = e.response.message;
                if (response) {
                        $("#error-message").html(response + "<br /><br />");
                }
            }
        } 
    This is causing the undefined issue.

    In order to receive the error message, I used this Destroy method, where I am forcing the deletion to have an error:

            public ActionResult Destroy([DataSourceRequest] DataSourceRequest request, FileManagerEntry entry)
            {
                ModelState.AddModelError("delete", "This folder is mapped in the database and cannot be deleted.");
    
                return Json(new[] { entry }.ToDataSourceResult(request, ModelState));
            }
    In the DataSource of the FileManager:
        .DataSource(ds =>
        {
            ds.Read(op => op
                .Type(HttpVerbs.Post)
                .Action("Read", "Home")
            );
            ds.Destroy(op => op
                .Type(HttpVerbs.Post)
                .Action("Destroy", "Home")
            );
            ds.Events(e => e.RequestEnd("onFileManagerRequestEnd"));
        })
    The Event handler:
    function onFileManagerRequestEnd(e) {
        if (e.type === "destroy" && e.response && e.response.Errors) {
            var messages = [];
            $.each(e.response.Errors, function (key, value) {
                if (value.errors) {
                    $.each(value.errors, function () {
                        messages.push(this);
                    });
                }
            });
    
            if (messages.length) {
                alert("Error:\n" + messages.join("\n"));
    
                $("#filemanager").getKendoFileManager().dataSource.read();
            }
        }
    }
    The result afer deletion:


    Attached is the sample project that I prepared for the case. Feel free to test it on your side. I hope you will like the result.

     

    Kind Regards,
    Anton Mironov

     

     

    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    commented on 09 Sep 2025, 06:08 PM

    Hi Anton,

    Many thanks for your reply.

    Using the sample project and the ModelState code that you provided, I have been able to achieve exactly what I needed, and in a neat way.

    Thank you very much for all of your help with this.

    Kind regards,

    Richard

    Anton Mironov
    Telerik team
    commented on 10 Sep 2025, 06:41 AM

    Hi Richard,

    Thank you for the kind words. I am glad to hear that the desired result has been achieved.

    If additional assistance or information is needed, do not hesitate to contact the Team.


    Greetings,
    Anton Mironov

    Tags
    FileManager
    Asked by
    Richard
    Top achievements
    Rank 4
    Bronze
    Bronze
    Iron
    Answers by
    Anton Mironov
    Telerik team
    Share this question
    or