使用 fetch 时如何从 MVC 控制器返回错误

Posted

技术标签:

【中文标题】使用 fetch 时如何从 MVC 控制器返回错误【英文标题】:How to return an error from a MVC Controller when using fetch 【发布时间】:2021-09-11 23:16:41 【问题描述】:

.Net 框架 4.6.1

我设置了以下代码来将文件上传到服务器。

如果数据中不存在文件名,我想将特定的错误消息返回给 fetch,以便将其显示给用户。

返回错误信息的正确方法是什么?

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 );

下面是响应的样子:

【问题讨论】:

这是什么版本的 .NET?是 Framework 还是 .NET Core? 在此处查看此答案***.com/a/43069917/2030565。你不想做的是抛出一个异常,因为你会得到一般的 500 错误。您可以返回一个合理的状态代码,例如 400 Bad Request,其中包含您的错误详细信息,然后您可以在 javascript 中对错误采取行动。如果您设计了一个通用响应“包”,因此错误和成功具有相同的字段,那么您可以用更少的代码行使您的 js 响应处理更通用。 @ReeceRussell: .net framework 4.6.1 -> 我也更新了这个问题,很抱歉忘记提出这个问题。 @Jasen:当我将它与您建议的帖子一起发回时,它仍然没有显示错误。我改成了badrequest,但是statusText什么都没设置? 空白的 statusText 似乎是使用 HTTP2 协议的working as intended。您可以使用浏览器验证***.com/questions/54091567/…。无论如何,您在服务器端设置的正文应该包含您传回给客户端的任何数据或消息。 【参考方案1】:

正如 Jasen 所写,U 总是可以 ````return BadRequest(jsonData)``` 并带有错误消息并在 frontApp 上显示。或任何其他操作结果

【讨论】:

【参考方案2】:

这是我的最终代码:

感谢@Jasen 的帮助!

我现在只需设置 statusCode 然后返回一个 JSON 对象即可。

我认为当它调用 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 );
        

【讨论】:

以上是关于使用 fetch 时如何从 MVC 控制器返回错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 和 ASP.NET MVC 从 AJAX 调用返回错误消息?

Spring MVC灵活控制返回json的值(自定义过滤字段)

Stackmob 不执行 fetch 请求而没有任何错误

Jquery Ajax,从 mvc.net 控制器返回成功/错误

如何从 ASP.NET MVC 控制器返回 Ajax“失败”?

如何使用 json 从 web.api 获取返回值到 mvc 控制器?