Mohsen Zahedi
Mohsen Zahedi

Reputation: 688

How can I catch the exceptions In Asp.net core that happen In thread

There are some tasks that I attached an action to. I have a middleware for observing all of the exceptions. Now, there is a problem with thread exception. I've already thrown an exception manually in body of the action, but when I throw an exception the application goes to break mode state and I can't monitor the exceptions.

Before mvc in configure, I put my error handling middleware

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    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 exception)
    {
        var code = HttpStatusCode.InternalServerError; 

        var result = JsonConvert.SerializeObject(new { error = exception.Message });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsync(result);
    }
}
//and this is the piece of code that run all tasks. 
foreach (var item in BotList)
{
            BotHandler BotObject = new BotHandler(item,conn);
            Task.Run(() => { BotObject.Run();});
}      
//

  public void Run()
    {

        //BotClient.StopReceiving();
        BotClient.OnMessage += BotOnMessageReceived;
        BotClient.OnMessageEdited += BotOnMessageReceived;
        BotClient.OnCallbackQuery += BotOnCallbackQueryReceived;

    }
     private async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
    {
       try
           {
              //do something
                string a = null;
                var b = a.ToString();
           }
       catch(Exception exp )
       {
         throw exp
       }
    }
}

Upvotes: 3

Views: 3853

Answers (2)

svoychik
svoychik

Reputation: 1327

As I understood you run this code in action of controller:

//and this is the piece of code that run all tasks. 
foreach (var item in BotList)
{
            BotHandler BotObject = new BotHandler(item,conn);
            Task.Run(() => { BotObject.Run();});
}  

The main problem is that you are trying to run the task for an already finished request. That is why ExceptionHandlingMiddleware (and actually other middlewares) can't handle anything. To fix your issue you can add try/catch block to handle an unexpected exception.

I would strongly advise not to start a background task during an HTTP request. It's error-prone approach as a task may shut down at any time and you won't even notice. Instead of this approach, it's better to use background task (msdn, SO Discussion), some kind of AWS lambda/Azure function or another task scheduler.

In case you need to do some recalculation job after HTTP method is called you may consider async message processing to trigger the process.

Upvotes: 3

Paweł Górszczak
Paweł Górszczak

Reputation: 574

if you go here https://msdn.microsoft.com/en-us/magazine/jj991977.aspx you will read that.

Exceptions from an Async Void Method Can’t Be Caught with Catch

So you cannot catch exception (the middleware cannot) which you are throwing in your BotOnMessageReceived method (in a Catch part).

So you have 2 solutions.

  1. Remove async keyword
  2. Or Catch app unhandled exceptions if its possible. For example in normal .net framework console app, you have event in App called unhandled exceptions, and can handle such situations like yours.

I have also found smth here, maybe it will help How do I catch unhandled exceptions in ASP .NET Core 2.0 before the page is rendered?

Upvotes: 2

Related Questions