Search code examples
c#handlerdelete-filefine-uploadercustom-error-handling

fine uploader delete custom error message not coming back


I am having trouble getting a custom error message back from my file delete handler. I am not sure but it looks like the delete is handled differently to the upload.

From the docs:

You may return any response you like, as the XMLHttpRequest object will be passed to your onDeleteComplete handler for further examination. However, the response code you return is important to Fine Uploader, as it uses this to determine if the delete has succeeded or not. The following response codes indicate success for this specific request: 200, 202, and 204. Any other response code indicates a failure.

In my server handler for the delete I have this to catch the error and send back response to FineUploader.

catch (Exception ex)
{
    //const string json = "{\"success\":false}";
    const string json = "{\"success\":false,\"error\":\"THIS IS THE ERROR\"}";
    //const string json = "{\"error\":\" HERE IS THE ERROR! \"}";
    var response = (Response)json;
    response.ContentType = "text/plain";
    //response.StatusCode = HttpStatusCode.InternalServerError; 
    return response;
}

I have tried sending back {"success":false} along with the error, just {"success":false} and just the error. I have checked that the json is valid. However it seems to do nothing at all. All that matters to FineUploader is response.StatusCode. If I send a fail response code then FineUploader recognises the error and displays the message for that code. It also comes back in errorReason in the onError callback.

If I do not set the response status code it defaults to OK and no error is raised.

I have looked at the example code for php and see this in the delete handler:

if (is_dir($target)){
    $this->removeDir($target);
    return array("success" => true, "uuid" => $uuid);
} else {
    return array("success" => false,
        "error" => "File not found! Unable to delete.".$url,
        "path" => $uuid
    );
}

Clearly, that code is sending back a "success":fail with a custom error message. But I can't work out in that code what response status is being sent back.

Update 1: Here is the js on the client to handler the server response:

callbacks: {
    onError: function(id, name, errorReason, xhrOrXdr) {
        alert(qq.format("Error on file number {} - {}.  Reason: {}", id, name, errorReason));
        console.log(errorReason);
}

So, am I doing something wrong?

Update 2:

Ok, I have had a look at onDeleteComplete and my client code now looks like this:

 callbacks: {
    onDeleteComplete: function(id, xhr, isError) {
        alert("onDeleteComplete => id is:" + id + " Is error?:" + isError);
    },
    onError: function(id, name, errorReason, xhrOrXdr) {
        alert(qq.format("onError => Error on file number {} - {}.  Reason: {}", id, name, errorReason));
        console.log(errorReason);
    },

Now when I delete a file in the browser I get the onError alert first and then the onDeleteComplete. In neither case can I find any way to show the error message I want to send back from my server handler. The onError always seems to just show the HttpStatus error message and not the one defined in my json response. The onDeleteComplete has no parameter to bring back the error.


Solution

  • I am not sure if it's just me but I found this confusing and inconsistent.

    For uploads you can do this:

    failedUploadTextDisplay: {
            mode: "custom",
            responseProperty: "errorMessage"
        },
    

    What this means is that your server can send back a custom response error and this will be displayed below the file in the event of an error.

    So my C# Nancy server code does this on error:

    catch (Exception ex)
                {
                    FormResponse.success = false;
                    FormResponse.errorMessage = ex.Message;
                    return Response.AsJson(FormResponse).WithStatusCode(HttpStatusCode.BadRequest);
                }
    

    This sends back json that looks like this:

    {"errorMessage":"A file with that name already exists and cannot be overwritten!","success":false}
    

    FineUploader then shows this message under the file like this:

    enter image description here

    Which is great. However for file delete there is no such feature I can find.

    So for unexpected delete failures I will have to find a workaround:

    I have the onDeleteComplete callback which I assumed could use to get the error:

    onDeleteComplete: function(id, xhr, isError) {
                if (isError) {
                    console.log("Error in delete!!");
                    if (typeof xhrOrXdr != 'undefined' && xhrOrXdr != null) {
                        console.log("resp text=" + xhrOrXdr.responseText);
                        var t = JSON.parse(xhrOrXdr.responseText);
                        console.log(t['errorMessage']);
    
                    }
                }
    

    But this does not work because when isError = true the xhr object is null. So there's no way to get the error in onDeleteComplete.

    It would be nice if FineUploader had something like this:

    failedDeleteTextDisplay: {
    mode: "custom",
    responseProperty: "errorMessage"
    

    },

    But it doesn't. So it looks like I have to handle the delete error in the OnError callback. But since I won't know which kind of action it is. Delete or Upload then I will have to send another parameter back in my json to handle the switch since I only need to change the default error message for failed deletes.

    So, my final workaround for now is this. The onError handler deals with both delete and upload errors. My server now sends back another parameter in the json called 'actionType'. This can either be 'delete' or 'upload'. If it's a delete action error then some jquery hides the default error messages and shows the new one.

    onError: function(id, name, errorReason, xhrOrXdr) {
                if (typeof xhrOrXdr != 'undefined' && xhrOrXdr != null) {
                    var t = JSON.parse(xhrOrXdr.responseText);
    
                    // if the error was result of delete then show the custom                     message on the panel
                    if (t["actionType"] === "delete") {
                        $("#CustomError").html("Delete failed: " +  t["errorMessage"] );
                        $("#ErrorContainer").hide();
    
                    }
    
                }
            },
    

    UPDATE: Well this is embarrassing. I raised this as a bug and it turns out it was my code at fault. This is a demonstration and reminder to me about the pitfalls of javascript. Id' been looking at this code for some time:

    onDeleteComplete: function(id, xhr, isError) {
                if (isError) {
                    console.log("Error in delete!!");
                    if (typeof xhrOrXdr != 'undefined' && xhrOrXdr != null) {
    

    It was only when Ray looked at my bug report that he spotted an obvious error. My function variable was called xhr but my code was looking for xhrOrXdr. I just didn't see it. And since it's javascript there were no complaints in the console. I am used to coding in C# with Resharper where that kind of thing is impossible. Neither Resharper or VS intellisense were able to warn me.

    So the bug was my bug and the onDelete callback works as described.

    It's a learning process..