异常无法冒充错误处理中间件吗?

时间:2019-07-08 18:44:03

标签: c# asp.net-core dependency-injection middleware

我有一块中间件,应该可以捕获我的异常并在发生异常时正确设置Http响应代码,但是看来无论我做什么,我仍然会收到OK响应。

这是中间件

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;

    /// <inheritdoc />
    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    /// <summary>
    /// Called by execution pipeline
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        var code = HttpStatusCode.InternalServerError; // 500 if unexpected

        var result = JsonConvert.SerializeObject(new { error = ex.Message });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsync(result);
    }
}

它像这样添加到我的创业公司中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseMiddleware(typeof(ErrorHandlingMiddleware));
    if (env.IsDevelopment())
    {
        //app.UseDeveloperExceptionPage();
    }else
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles(new StaticFileOptions
    {
        ServeUnknownFileTypes = true
    });
    app.UseDefaultFiles();
    app.UseCookiePolicy();
    app.UseMvc();

    app.UseCors("CorsPolicy");

    app.UseMvcWithDefaultRoute();

    app.UseSwaggerAndUI(Configuration)
       .UseCustomHealthCheck();
}

引发错误的代码是:

public Task<string> SaveFileAsync(string path, byte[] file, string fileType, CancellationToken cancellationToken = default)
{
    var filename = _filenameProvider.GetFilename(path, fileType);
    var fullPath = _fileSystem.Path.Combine(path, filename).Replace('/', '\\');

    try
    {
        _fileSystem.Directory.CreateDirectory(fullPath);
        // Error in the FileSystem abstraction library: https://github.com/System-IO-Abstractions/System.IO.Abstractions/issues/491
        //await _fileSystem.File.WriteAllBytesAsync(fullPath, file, cancellationToken);

        _fileSystem.File.WriteAllBytes(fullPath, file);

        return Task.FromResult(filename);
    }
    catch (Exception ex)
    {
        Log.Error(ex.Message, nameof(SaveFileAsync), _userId);

        throw;
    }
}

控制者是:

public class PatientDocumentController : BaseController
{
    private readonly IPatientFilePusher _patientFilePusher;


    /// <inheritdoc />
    public PatientDocumentController(IPatientFilePusher filePusher)
    {
        _patientFilePusher = filePusher;
    }

    /// <summary>
    /// Pushes a patient file to the emr
    /// </summary>
    /// <param name="request">Contains the file data.</param>
    /// <param name="token">A auto-generated token that allows for halting execution.</param>
    /// <returns>Ok when complete.</returns>
    [HttpPost]
    public async Task<IActionResult> PushPatientDemographicsAsync([FromBody] FilePushRequest request, CancellationToken token)
    {
        await _patientFilePusher.PushFileAsync(request, token);

        return Ok();
    }
}

返回的响应正文包含异常,但Http状态代码仍为200。永远不会调用中间件上的catch分支。

1 个答案:

答案 0 :(得分:0)

您有一个具有异步签名但不遵循异步处理方式的函数:

public Task<string> SaveFileAsync(string path, byte[] file, string fileType, CancellationToken cancellationToken = default)

当函数返回Task / Task<T>时,应捕获该函数引发的任何异常并将其放置在该返回的任务上。 async关键字将为您做到这一点。

因此,您应该将函数更改为async

public async Task<string> SaveFileAsync(string path, byte[] file, string fileType, CancellationToken cancellationToken = default)
{
    var filename = _filenameProvider.GetFilename(path, fileType);
    var fullPath = _fileSystem.Path.Combine(path, filename).Replace('/', '\\');

    try
    {
        _fileSystem.Directory.CreateDirectory(fullPath);
        // Error in the FileSystem abstraction library: https://github.com/System-IO-Abstractions/System.IO.Abstractions/issues/491
        //await _fileSystem.File.WriteAllBytesAsync(fullPath, file, cancellationToken);

        _fileSystem.File.WriteAllBytes(fullPath, file);

        return filename;
    }
    catch (Exception ex)
    {
        Log.Error(ex.Message, nameof(SaveFileAsync), _userId);

        throw;
    }
}

或自己将异常放在返回的任务上:

public Task<string> SaveFileAsync(string path, byte[] file, string fileType, CancellationToken cancellationToken = default)
{
    try
    {
        var filename = _filenameProvider.GetFilename(path, fileType);
        var fullPath = _fileSystem.Path.Combine(path, filename).Replace('/', '\\');

        _fileSystem.Directory.CreateDirectory(fullPath);
        // Error in the FileSystem abstraction library: https://github.com/System-IO-Abstractions/System.IO.Abstractions/issues/491
        //await _fileSystem.File.WriteAllBytesAsync(fullPath, file, cancellationToken);

        _fileSystem.File.WriteAllBytes(fullPath, file);

        return Task.FromResult(filename);
    }
    catch (Exception ex)
    {
        Log.Error(ex.Message, nameof(SaveFileAsync), _userId);

        return Task.FromException<string>(ex);
    }
}