Search code examples
c#asp.net-mvcfetch

How to return an error from a MVC Controller when using fetch


.Net framework 4.6.1

I have the below code set up to upload a file to the server.

If the file name is not present in the data, I want to throw a specific error message back to the fetch so I can display it to the user.

What is the proper way to return the error message?

fetch(url, {
    method: 'POST',
    body: data,
}).then(function (response) {
     if (!response.ok) {
         return response.json()
             .then(function (obj) {
                 throw Error(obj.ErrorMessage)
             })
     }
     else {
         return response.json()
             .then(json => {
                 /*further processing */
             })
     }
 }).catch(/* work with the error */)


/// Uploads the file chunk.
/// </summary>
/// <param name="collection">The collection.</param>
/// <returns>
/// ActionResult
/// </returns>
[HttpPost]
[ValidateAntiForgeryToken]
[Log(ClickTrackingItemTypeConstants.DataPost)]
public async Task<ActionResult> UploadFileChunk(FormCollection collection)
{
    var fileDataParam = JsonConvert.DeserializeObject<UploadFileChunkFileDataModel>(collection["fileDataParam"]);

    if (fileDataParam == null)
    {
        throw new RubixGenericException(nameof(fileDataParam));
    }

    fileDataParam.FileName = string.Empty;
    if (string.IsNullOrWhiteSpace(fileDataParam.FileName) == true)
    {
        throw new Exception("error...");
    }

    fileManagerUtilities.AppendContentToFile(fileDataParam.FileGuid, fileDataParam.FileExtension, Request.Files[0]);

    if (fileDataParam.ChunkIndex == (fileDataParam.ChunkTotalCount - 1))
    {
        System.Diagnostics.Debug.WriteLine("file can be uploaded now");
    }

    return Json(new { success = true });
}

Here is what the response looks like:

enter image description here


Solution

  • Here is my final code that works:

    Thanks @Jasen for your help!

    I have it working now with just setting the statusCode and then returning a JSON object.

    I think I was not parsing it properly when it calls response.Json()

    function uploadFileChunkFileManager(fileData, chunksInfo, destinationDir) {
        var deferred = $.Deferred();
    
        const formData = new FormData();
    
        formData.append('file', chunksInfo.chunkBlob);
    
        let fileManagerJsParam = getFileManagerParams(destinationDir, true);
    
        if (chunksInfo.chunkIndex === 0) {
            chunksInfo.customData.fileGuid = uuidv4();
        }
    
        let fileDataParam = {
            BytesUploaded: chunksInfo.bytesUploaded,
            ChunkIndex: chunksInfo.chunkIndex,
            ChunkTotalCount: chunksInfo.chunkCount,
            FileIndex: chunksInfo.fileIndex,
            FileName: fileData.name,
            FileSize: fileData.size,
            FileType: fileData.type,
            FileGuid: chunksInfo.customData.fileGuid,
            FileManagerJsParam: fileManagerJsParam
        }
    
        formData.append('fileDataParam', JSON.stringify(fileDataParam));
        formData.append('__RequestVerificationToken', $('[name=__RequestVerificationToken]').val());
    
        let url = BuildSafeURL(baseEndPoint + "UploadFileChunk", null);
    
        fetch(url, {
            method: 'POST',
            body: formData,
        }).then(function (response) {
            if (!response.ok) {
                return response.json()
                    .then(function (error) {
                        deferred.reject({
                            errorId: 27000,
                            errorText: error.errorMessage,
                            fileItem: destinationDir,
                        })
                    }).catch(error => {
                        //error handling for json parsing errors (empty body etc.)
                        console.log("Successful request, Could not parse body as json", error);
                        deferred.reject(uploadFileGenericErrorMessage(destinationDir));
                    })
            }
            else {
                deferred.resolve();
                console.log('done... with upload..')
            }
        }).catch(function (error) {
            console.log(error);
            deferred.reject(uploadFileGenericErrorMessage(destinationDir));
        })
    
        return deferred.promise()
    }
    
            /// <summary>
            /// Uploads the file chunk.
            /// </summary>
            /// <param name="collection">The collection.</param>
            /// <returns>
            /// ActionResult
            /// </returns>
            [HttpPost]
            [ValidateAntiForgeryToken]
            [Log(ClickTrackingItemTypeConstants.DataPost)]
            public async Task<ActionResult> UploadFileChunk(FormCollection collection)
            {
                var fileDataParam = JsonConvert.DeserializeObject<UploadFileChunkFileDataModel>(collection["fileDataParam"]);
    
                if (fileDataParam == null)
                {
                    throw new GenericException(nameof(fileDataParam));
                }
    
                if (string.IsNullOrWhiteSpace(fileDataParam.FileName) == true)
                {
                    Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return Json(new { errorMessage = "File name is required." });
                }
    
                fileDataParam.FileExtension = Path.GetExtension(fileDataParam.FileName);
    
                if (string.IsNullOrWhiteSpace(fileDataParam.FileExtension) == true)
                {
                    Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return Json(new { errorMessage = "File extension is required." });
                }
    
                if (Request.Files.Count == 0)
                {
                    throw new GenericException("Request.Files.Count is 0");
                }
    
                if (Request.Files.Count > 1)
                {
                    throw new GenericException("Request.Files.Count is greater than 2");
                }
    
                fileManagerUtilities.AppendContentToFile(fileDataParam.FileGuid, fileDataParam.FileExtension, Request.Files[0]);
    
                if (fileDataParam.ChunkIndex == (fileDataParam.ChunkTotalCount - 1))
                {
                    System.Diagnostics.Debug.WriteLine("file can be uploaded now");
                }
    
                // allow to build until I update the code to save to the db
                await fileManagerUtilities.DownloadFile("285", 107).ConfigureAwait(false);
    
                return Json(new { success = true });
            }