【问题标题】:Better Exception Message in Extension Method扩展方法中更好的异常消息
【发布时间】:2015-02-15 20:07:31
【问题描述】:

我们有以下扩展方法:

public static class HttpResponseMessageExtensions
{
    [DebuggerStepThrough]
    public static async Task<T> ToAsync<T>(this HttpResponseMessage response)
    {
        if (!response.IsSuccessStatusCode)
        {
            var message = string.Format("There was a problem extracting the content from the response. Status: {0}. Reason: {1}", response.StatusCode, response.ReasonPhrase);
            var exception = new Exception(message);
            throw exception;
        }

        var stringContent = await response.Content.ReadAsStringAsync();

        return JsonConvert.DeserializeObject<T>(stringContent);
    }
}

这种方法有几个问题。我很好奇的是调试 MVC 项目时的源错误,我们将扩展代码本身作为错误:

Line 16:                 var message = string.Format("There was a problem extracting the content from the response. Status: {0}. Reason: {1}", response.StatusCode, response.ReasonPhrase);
Line 17:                 var exception = new Exception(message);
Line 18:                 throw exception;

理想情况下,我们会在调用方法中使用这一点,因为这更有帮助。

堆栈跟踪的帮助更小:

[Exception: There was a problem extracting the content from the response. Status: InternalServerError. Reason: Internal Server Error]
   Brightree.HomeHealth.Extensions.<ToAsync>d__0`1.MoveNext() in c:\code\CareAnyware\Trunk\HomeHealth\HomeHealth.SDK\Extensions\HttpResponseMessageExtensions.cs:18
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
   Brightree.HomeHealth.<Login>d__7.MoveNext() in c:\code\CareAnyware\Trunk\HomeHealth\HomeHealth.SDK\Users.cs:44
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
   Brightree.HomeHealth.Infrastructure.<Authenticate>d__4.MoveNext() in c:\code\CareAnyware\Trunk\HomeHealth\HomeHealth.SDK\Infrastructure\HomeHealthContext.cs:235
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   Brightree.HomeHealth.Web.Controllers.<Login>d__26.MoveNext() in c:\code\CareAnyware\Trunk\HomeHealth\HomeHealth.Web\Controllers\AccountController.cs:66
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task) +61
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +114
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult) +66
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +47
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +49
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +117
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +323
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +323
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +323
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +323
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +44
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +47
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +50
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +72
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129

我们可以实施一些措施来提供更多有用的信息吗?

【问题讨论】:

  • Stephen Cleary 的异步诊断可能会有所帮助:github.com/StephenCleary/AsyncDiagnostics/tree/master/src/…
  • 谢谢!我会试一试——有几件事会跳出来:“有明确的运行时影响。” - 好的,我们可以在调试模式下使用它,没什么大不了的。 “PostSharp 依赖项。” - 需要检查许可等,因为这是商业项目。
  • 您可以在异常中包含实际的响应文本,以便为调用者提供足够的信息以供他们调试。

标签: c# debugging exception async-await extension-methods


【解决方案1】:

关于更多有用的信息,这可能是Caller Information 属性的良好候选者。

public static class HttpResponseMessageExtensions
{
    [DebuggerStepThrough]
    public static async Task<T> ToAsync<T>(this HttpResponseMessage response, [CallerMemberName] string callerName = null, [CallerFilePath] string callerFilePath = null, [CallerLineNumber] int callerLine = -1)
    {
        if (!response.IsSuccessStatusCode)
        {
            var message = string.Format("There was a problem extracting the content from the response. Status: {0}. Reason: {1}. Calling method is {2} in {3}:line {4}", response.StatusCode, response.ReasonPhrase, callerName, callerFilePath, callerLine);
            var exception = new Exception(message);
            throw exception;
        }

        var stringContent = await response.Content.ReadAsStringAsync();

        return JsonConvert.DeserializeObject<T>(stringContent);
    }
}

【讨论】:

    猜你喜欢
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2021-07-27
    相关资源
    最近更新 更多