1

.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

ttaylor27272727
  • 195
  • 3
  • 18
  • What version of .NET is this? Is it Framework or .NET Core? – Reece Russell Jun 29 '21 at 18:50
  • 1
    See this answer here https://stackoverflow.com/a/43069917/2030565. What you don't want to do is throw an exception as you'll get the generic 500 error. You can return a sensible status code like 400 Bad Request with a body containing your error details, then you can act on the error in JavaScript. If you devise a common response "package" so errors and successes have identical fields, then you can make your js response handling more generic with less lines of code. – Jasen Jun 29 '21 at 18:50
  • @ReeceRussell: .net framework 4.6.1 -> I updated the question as well, sorry about forgetting to put that. – ttaylor27272727 Jun 29 '21 at 19:09
  • @Jasen: it still isn't showing the error when I sent it back with the post you suggested. I changed it to badrequest, but statusText doesn't have anything set? – ttaylor27272727 Jun 29 '21 at 21:01
  • The blank statusText appears to be [working as intended](https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText) with the HTTP2 protocol. You can verify with your browser https://stackoverflow.com/questions/54091567/how-to-check-if-a-website-has-http-2-protocol-support. In any case, the body you set server side should contain any data or message you pass back to the client. – Jasen Jun 29 '21 at 23:57
  • @Jasen: I thought `statusText` was something different and it would have the message. I think I have it fixed and I am about to post my solution. Your links did help! Thank you. – ttaylor27272727 Jun 30 '21 at 00:06

2 Answers2

2

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 });
        }
ttaylor27272727
  • 195
  • 3
  • 18
0

As Jasen wrote, U can always ````return BadRequest(jsonData)``` with an error message and show this on the frontApp. Or any other action result

benuto
  • 292
  • 1
  • 6