问题  CustomExceptionFilter和GlobalExceptionHandler有什么区别?

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
你好,

在我的asp.net Web API中,我同时使用GlobalExceptionHandler和CustomExceptionFilter。我认为他们做了同样的工作,向客户端隐藏了实际的错误并发送给他们"HTTP 500-内部服务器错误。请与您的管理员联系。"回复。我想知道是否删除GlobalExcepitonHandler并将Nlog添加到CustomExceptionFilter中,仍然可以发送相同的响应并记录错误吗?您对此有何看法?

UnhandledExceptionLogger无法捕获所有错误,这就是为什么我想在其中之一中添加日志记录的原因。

CustomExceptionFilter:
C#:
public class CustomExceptionFilter : ExceptionFilterAttribute
    {

        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            base.OnException(actionExecutedContext);


            var response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                //Content = new StringContent("An unhandled exception was thrown by service."),
                ReasonPhrase = "HTTP 500-内部服务器错误。请与您的管理员联系。"
            };

            actionExecutedContext.Response = response;
        }
    }

GlobalExceptionHandler:
C#:
public class GlobalExceptionHandler : ExceptionHandler
    {
        
        public override void Handle(ExceptionHandlerContext context)
        {
            var result = new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent("HTTP 500-内部服务器错误。请与您的管理员联系。"),
                ReasonPhrase = "Exception"
            };

            
            context.Result = new ErrorMessageResult(context.Request, result);
        }

        public class ErrorMessageResult : IHttpActionResult
        {
            private HttpRequestMessage _request;
            private readonly HttpResponseMessage _httpResponseMessage;

            public ErrorMessageResult(HttpRequestMessage request, HttpResponseMessage httpResponseMessage)
            {
                _request = request;
                _httpResponseMessage = httpResponseMessage;
            }

            public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
            {
                return Task.FromResult(_httpResponseMessage);
            }
        }

      }
UnhandledExceptionFilter:
C#:
public class UnhandledExceptionLogger : ExceptionLogger
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        public override void Log(ExceptionLoggerContext context)
        {
            var timestamp = DateTime.UtcNow;

            //NLOG
            NLog(logger, context.Exception, timestamp);
        }

        private void NLog(Logger logger, Exception message, DateTime timestamp)
        {
            var sb = new StringBuilder();
            sb.AppendLine(message.ToString());
            sb.AppendLine(timestamp.ToLongDateString());
            logger.Error(sb.ToString());
        }
    }
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
是的,我再读一遍,我拥有所有这些异常级别。当我添加CustomExceptionFilter并在其中使用Nlog时,出现了此错误。

C#:
2019-08-19 22:26:43.5956||ERROR|Game.Handlers.CustomExceptionFilter|System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at BusinessService.Utility.Utilities.<CallRazer>d__3.MoveNext() in C:\Users\197199\Documents\Visual Studio 2017\Projects\Game\BusinessService\Utility\Utilities.cs:line 138
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at BusinessService.GameServicesTest.<CallProducts>d__11.MoveNext() in C:\Users\197199\Documents\Visual Studio 2017\Projects\Game\BusinessService\GameServicesTest.cs:line 478
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at BusinessService.GameServicesTest.<GameProducts>d__10.MoveNext() in C:\Users\197199\Documents\Visual Studio 2017\Projects\Game\BusinessService\GameServicesTest.cs:line 449
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Game.Controllers.LoadTestController.<PostProducts>d__5.MoveNext() in C:\Users\197199\Documents\Visual Studio 2017\Projects\Game\Game\Controllers\LoadTestController.cs:line 205
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__1`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
是httpclient超时吗?
好吧。如果您的httpclient被另一个线程或处置方法终止。是吗?鉴于您在连接池和线程池方面遇到问题,因此我不排除任何问题。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
我增加了超时时间,但不幸的是没有帮助我的峰值测试。

C#:
 //Timeout
_httpClient.Timeout = TimeSpan.FromSeconds(600);
//Call Game
var response = await _httpClient.PostAsync("//test.com/" + url, content);
return response;
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
如果问题出在第三方服务上怎么办?我的意思是吧?一直以来,我一直试图在代码中查找错误,但我认为这可能是由于第三方rest API测试环境所致。
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
就像您的其他一些问题一样,此问题似乎由服务器管理员承担。我回去回顾你的一些帖子 1#2#,并且您的服务器没有响应,很可能是因为它需要重新配置。看 关于这个:
截图_29.jpg

还有这个 :
截图_31.jpg

由于存在网络连接,DNS故障,服务器证书验证或超时等根本问题,因此请求失败。 〜微软

这似乎很明显,您的大多数问题都驻留在服务器上,并且它们没有响应,这一事实应该告诉您某些问题是不正确的。如果您无法连接到它们,那么您如何期望应用程序连接到它们?截至目前,您来自gameultan的子域将重定向到新的目的地= > http://qa-api.mol.com/pinstore/ 似乎还可以,而且响应也很好,不会像上面那样停滞不前。 @raysefo 您是唯一的开发人员,还是有其他人参与此项目?我之所以这样问,是因为我从事过许多类似的项目,在这些项目中,网络/安全/技术管理员由于对服务器的更改而不必要地引起了很多头痛,如果这是您的情况,则需要告诉他们以努力直到您首先完成自己的工作,并且您应该请求完全访问权限才能自己设置系统。完成后,他们可以保护它。
截图_33.jpg

您的服务器正在通过IP响应ping请求。您的子域没有,但是现在将其重定向到其他地方。我注意到您也在使用安全连接,而您的代码却没有。根据Microsoft的说法,这也可能导致应用程序中的异常。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
谢谢你的解释 @谢平.

您是唯一的开发人员,还是有其他人参与此项目?
是的,我是这个项目中唯一的一个。正如我在我的一篇帖子中提到的那样,我们正在使用的服务器(185.201.212.218)托管在云中。我具有管理员权限,但对服务器管理的经验很少,主要是Google Engineering  :) //teststore.gamesultan.com/ 是我正在调用的第三方rest API。他们允许我们的IP(185.201.212.218)访问其API。

您的子域没有,但是现在将其重定向到其他地方。
恐怕我不明白你的意思"your subdomain"?我的服务器IP是185.201.212.218。

我注意到您也在使用安全连接,而您的代码却没有。
我也不明白。请详细说明一下吗?
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
让我们一次在这里...在上面的答复中,单击1#,然后在该页面上进行搜索,您将看到我所不喜欢的内容。
C#:
                        //Call Game Sultan
                        var response = await _httpClient.PostAsync("//teststore.gamesultan.com/" + url, content);
我了解您正在尝试插入该服务器,但是该服务器没有响应。更不用说它正在将其流量引向新的域名,正如我上面已经解释的那样。在您的服务器,第3方以及与您的设置有关的任何人之间,都存在问题。查看第一个扰流板中的屏幕截图,您的 或/和 服务器没有响应。坦白说,我不会使用云服务器,但这是另一次讨论。另外,此IP的目的是什么:185.201.212.218?这是您的网站所在的位置还是什么?我只是想对您实际上正在做的事情有一个清晰的了解。

您需要自己对此进行一些查询,并向您的托管服务提供商寻求有关您要执行的操作的帮助,以便您具有正确的服务器设置。如果你有一个 受管服务器 通过托管服务提供商,您应该在今天晚上或明天配置好服务器并使其正常运行。您还应该向第三方询问有关您的第三方提供商的流量,并请他们确认您的请求正在影响他们的系统。您还应该问他们一次可以发出多少个请求。他们可能会限制您的互动。如果您要向他们的系统发送大量请求,则可以在他们的一端完成此操作。
一直以来,我一直试图在代码中查找错误,但我认为这可能是由于第三方rest API测试环境所致。
让我们坚持先找出几件事,然后再从那里转到其他一些职位,在这些职位上我将解决一些细微的差异。另外,这个gameultan.com是否具有我们可以阅读的开放API?
我注意到您也在使用安全连接,而您的代码却没有。 =>我的意思是说,就像他们一样。 gameultan正在使用https,并且有一些协议可以发布到安全连接。您可以自己在那附近变兵。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
谢谢 @谢平.

同样,此IP的目的是什么:185.201.212.218?这是您的网站所在的位置还是什么?我只是想对您实际上正在做的事情有一个清晰的了解。
我的其余API在此服务器中。 (185.201.212.218)这是流程;客户调用我的API,而我的API调用此第三方API。

另外,这个gameultan.com是否具有我们可以阅读的开放API?
不幸的是,没有开放的API。

我将建议我们的服务器管理员和第三方管理员进行测试,以找出问题所在。我将使Google工程技术发布到安全连接的协议。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
希望我们可以与管理员进行测试。暂时,我做了另一个测试。将线程数25增加25。当延迟超过100秒时,我得到了System.Threading.Tasks.TaskCanceledException:任务被取消的错误。

2019-08-21 22_42_51-在Table.jmx中查看结果(T__Home_在Table.jmx中查看结果)-Apache JMe ... png
2019-08-21 22_42_51-在Table.jmx中查看结果(T__Home_在Table.jmx中查看结果)-Apache JMe ... png
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
我首先要离开云托管。如果主服务器出现故障,则可以使用云服务器。但是,然后我将要确保您的服务器无论运行的是什么,都具有正确的配置。这完全是服务器管理人员的责任;无论他们是谁。然后,我将与游戏迷们进行核实,以确保他们正确地为您提供了所需的访问权限,并且确保他们没有误配置某些东西,因为所谓的API并不公开,因此并不表明他们拥有经过良好测试的平台,可以无错运行。

坦白说,我担心使用一家不知道如何正确设置自己的DNS记录的公司提供的服务。没有ptr记录,不正确的mx记录,以及允许递归查询,这是一件很糟糕的事情。是的,我不会屏息,因为他们知道服务器配置和安全性方面的工作。您是否知道其他使用gameultan的网站?希望您很快就能对它进行排序。得到#11的答案后,将其发布。

顺便说一句,虽然我确实相信您的问题是外部的,但竭尽全力以 确保 使用async / await时不会丢弃您的HttpClient。快速检查表明,如果处置了客户端,则可能会出现此错误。检查您的日志中错误的行号。在错误上放置一个断点,当错误发生时,您可以检查 CancellationToken.IsCancellationRequested属性(System.Threading) 如果返回的是false,则可以肯定在某个地方超时了。正如我之前建议的那样,在服务器上获取VNC并在该服务器上安装VS Community,然后从实时服务器测试您的应用程序。在开发中可能起作用的东西,在生产中并不总是起作用。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
顺便说一句,虽然我确实相信您的问题是外部的,但竭尽全力以 确保 使用async / await时不会丢弃您的HttpClient。快速检查表明,如果处置了客户端,则可能会出现此错误。检查您的日志中错误的行号。在错误上放置一个断点,当错误发生时,您可以检查 CancellationToken.IsCancellationRequested属性(System.Threading) 如果返回的是false,则可以肯定在某个地方超时的情况下押注您的钱
是的,我在云服务器上安装了VS社区,有时我会进行远程调试。那么,您是说我在用Jmeter进行负载测试时应该调试吗?因为我不确定在负载测试期间调试是否正确/容易。

我可以在此处记录IsCancellationRequested而不进行调试吗?
C#:
try
{
                     
       //Timeout
       _httpClient.Timeout = TimeSpan.FromSeconds(600);
        //Call Game Sultan
         var response = await _httpClient.PostAsync("//test.com/" + url, content);
         return response;
}
catch (TaskCanceledException)
{
        //Nlog here
                     
        
bool value = e.CancellationToken.IsCancellationRequested;
string time;
if (_httpClient.Timeout.TotalHours > 1)
 {
            time = $"{_httpClient.Timeout.TotalHours:N1} hours";
 }
else if (_httpClient.Timeout.TotalMinutes > 1)
 {
             time = $"{_httpClient.Timeout.TotalMinutes:N1} minutes";
 }
 else if (_httpClient.Timeout.TotalSeconds > 1)
 {
            time = $"{_httpClient.Timeout.TotalSeconds:N1} seconds";
 }
 else
 {
           time = $"{_httpClient.Timeout.TotalMilliseconds:N0} milliseconds";
}
 throw new TimeoutException($"No response after waiting {time}. Value {value}");
 }
 finally
 {
         content.Dispose();
 }

顺便说一句,我必须将CancellationToken传递到此CallRazer方法中,以使其可取消,对吗?我没有这样的代码。我的意思是这一定是其他东西,但我会尝试进行调试并确保。

您是否知道其他使用gameultan的网站?
是的,据我所知,它们正在运行。
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
不,您在一开始不进行负载测试时就进行调试,您只需要在不连接调试器的情况下以及应用程序崩溃时运行负载测试即可。检查您的日志以了解崩溃的行。然后将该行包装在try catch中,然后在catch块中,将一个断点放置在catch上(exceptiontype ex) {打开括号。 然后调试代码,并在连接调试器时以及遇到相同错误时再次运行负载测试器。您应该能够找出原因。
我可以在此处记录IsCancellationRequested而不进行调试吗?
您将使用IsCancelationRequested检查是否在您的代码中调用了取消请求。它返回布尔值,并请求令牌。你可以在这里看到它的用法 CancellationTokenSource类(System.Threading)
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
这意味着某些事情正在取消您的操作/任务。欢迎使用并行编程。
确保 使用async / await时不会丢弃您的HttpClient。快速检查表明,如果处置了客户端,则可能会出现此错误。
检查所有逻辑,并跟踪取消呼叫的发起位置。
IsCancellationRequested 属性返回true,任务将其解释为确认取消并转换为Canceled状态。如果您不使用 等待 或者 等待所有 等待任务的方法,然后任务将其状态设置为 取消 .
您可以在文档中找到答案,以取消任务 任务取消

希望这有助于解决这一问题。
 

Raysefo

知名会员
已加入
2019年2月22日
留言内容
194
编程经验
10+
谢谢 @谢平 为您的建议。

检查所有逻辑,并跟踪取消呼叫的发起位置。
问题是我没有调用任何取消令牌。如果我正在调用取消令牌,它将在方法签名中,对吗?但是没有下面的代码。

C#:
public static async Task<HttpResponseMessage> CallRazer(GameRequest gameRequest, string url, [B][I]CancellationToken cancellationToken[/I][/B])
        {
[B]            [/B]FormUrlEncodedContent content = null;

            if (url == "Product/")
            {
                try
                {
                   
                    //Timeout
                    _httpClient.Timeout = TimeSpan.FromMinutes(3);
                    //Call Game Sultan
                    var response = await _httpClient.PostAsync("//teststore.gamesultan.com/" + url, content,[B] [I]cancellationToken[/I]);
                    [/B]return response;
                }
                catch (Exception e)
                {...
                   
                    //code here

我认为只有一种选择是处理HTTP客户端。但是如何处置呢?下次遇到断点时,我将检查httpclient。

这是使用http客户端的正确方法吗?

C#:
public class UtilitiesTest
    {
        private static readonly HttpClient _httpClient = new HttpClient();


        public static GameRequest CreateSignature(GameRequestDto game, GameServicesTest.RequestType type)
        {
        //some code
        }

        public static string GetMd5Hash(HashAlgorithm md5Hash, string input)
        {
         //some code   
        }

        public static async Task<HttpResponseMessage> CallRazer(GameRequest gameRequest, string url)
        {
            FormUrlEncodedContent content = null;

            if (url == "Product/")
            {
                try
                {
                    //some code
                    //Timeout
                    _httpClient.Timeout = TimeSpan.FromMinutes(5);
                    //Call Game Sultan
                    var response = await _httpClient.PostAsync("//teststore.gamesultan.com/" + url, content);
                    return response;

                    
                }
                catch (Exception e)
                {
                    
                    string time;
                    if (_httpClient.Timeout.TotalHours > 1)
                    {
                        time = $"{_httpClient.Timeout.TotalHours:N1} hours";
                    }
                    else if (_httpClient.Timeout.TotalMinutes > 1)
                    {
                        time = $"{_httpClient.Timeout.TotalMinutes:N1} minutes";
                    }
                    else if (_httpClient.Timeout.TotalSeconds > 1)
                    {
                        time = $"{_httpClient.Timeout.TotalSeconds:N1} seconds";
                    }
                    else
                    {
                        time = $"{_httpClient.Timeout.TotalMilliseconds:N0} milliseconds";
                    }

                    throw new TimeoutException($"No response after waiting {time}.");
                }
              
            }
            
        }
    }

这就是我所说的实用程序。
C#:
private async Task<HttpResponseMessage> CallProducts()
        {
            //some code
            //Create signature
            var products = UtilitiesTest.CreateSignature(productsDto, RequestType.Product);

            #region Call Razer for products

            //Call Razer for initiation
            var response = await UtilitiesTest.CallRazer(products, "Product/");

            var htmlResponse = await response.Content.ReadAsStringAsync();
            var model = JsonConvert.DeserializeObject<ProductResponseDto>(htmlResponse);

            //some code

            return response;
        }
 
Last edited:

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,933
地点
英国
编程经验
10+
There is nothing worse that giving someone the documentation for something, and then they come back and ask you how to do it. Then you tell me in the same line The thing is I am not calling any cancellation token.. Which you clearly didn't give much consideration to my post when I gave you the answer :
如果您不使用Wait或WaitAll方法来等待任务,则该任务仅将其状态设置为Canceled。
But how can it be disposed?
可能 被处置。检查您的班级,或者检查您在班级某处定义的using语句。这就是调试器的用途。正如我所说,我们只能提供很多帮助。
 
最佳 底部