11

I have an ASP.NET MVC app with WebAPI controllers, and a console app that uses these controllers. The console app runs from a scheduled task and fetches data from remote sources, parses it, and posts it to the MVC app before exiting.

This works well for several of the controllers, but one of the calls is crashing the console app without throwing an exception. The caller code which is used for all the controllers:

    public async Task<string> Post<T>(string urlRoot, string url, T data)
    {
        var result = "";
        try
        {
            var httpClient = GetHttpClient(urlRoot);
            var response = await httpClient.PostAsJsonAsync(url, data); // Exits here
            if (response.IsSuccessStatusCode)
            {
                result = await response.Content.ReadAsAsync<string>();
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        return result;
    }

The program exits when calling await httpClient.PostAsJsonAsync(url, data). Using breakpoints, neither the catch block nor the if statement are reached. The call is being made however, as the web API controller is being called with the correct data.

The programs share the same code for the T being passed across the API call.

From the output window:

The program '[9640] ProgramName.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

I was wondering whether the size of the posted data could be a problem, but I've not found any documentation stating size limits.

So my questions are:

  1. What could be causing the console app to prematurely exit?
  2. How can I detect this and prevent the program exiting?
harriyott
  • 10,505
  • 10
  • 64
  • 103
  • Could you give us a brief description of your call stack from `Main` to `Post`? i.e., are you using `async void` anywhere, are you `await`ing all your `Task`s, etc. – Stephen Cleary Apr 16 '13 at 12:23
  • 1
    I had this happen for a very similar scenario. What I did was run `Fiddler` and then I saw the `Http` response that was being returned and the issue was `JSON.Net` was unable to serialize some sub-objects used in the response. – Elad Lachmi Apr 29 '14 at 20:36
  • 1
    This may be useful for someone else - After trying all the suggestions in this thread, I finally deleted my bin & obj folders, cleaned and rebuilt my project, restarted Visual Studio. Problem went away after that. VS2015sp3 WebAPI2 MVC4 – Daniel Szabo Nov 09 '16 at 09:29

5 Answers5

2

One of possible problems, that you just don't await execution of Post method. Here is simplified version of what i am talking about:

    static void Main(string[] args)
    {
        Action testAction = async () =>
        {
            Console.WriteLine("In");
            await Task.Delay(100);
            Console.WriteLine("First delay");
            await Task.Delay(100);
            Console.WriteLine("Second delay");
        };
        testAction.Invoke();
        Thread.Sleep(150);
    }

testAction will be aborted on second await Task, and console exits with 0 code. And output will be:

   In
   First delay
   Press any key to continue . . .

In my case, i would just add Console.ReadKey() call at the end of Main method. In your case something different might be required

Uriil
  • 11,948
  • 11
  • 47
  • 68
1

Please take a look at this question witch enumerates some Exceptions you need to handle:

.NET Global exception handler in console application

Application.ThreadException += MYThreadHandler;

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Also consider this aproach for Task Exceptions:

static void Main(string[] args)
{
    Task<int> task = new Task<int>(Test);
    task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
    task.Start();
    Console.ReadLine();
}

static int Test()
{
    throw new Exception();
}

static void ExceptionHandler(Task<int> task)
{
    var exception = task.Exception;
    Console.WriteLine(exception);
}

You can find more detail in one of the answers of this question:

catch exception that is thrown in different thread

Community
  • 1
  • 1
csharpwinphonexaml
  • 3,659
  • 10
  • 32
  • 63
0
  1. Once you hit await control will be returned to the caller of Post.

  2. Rather than have await in the post method, use ContinueWith from the returned task, something like: Task continuation on UI thread or Wait on the returned task: http://msdn.microsoft.com/en-gb/library/dd537610.aspx

Community
  • 1
  • 1
HadleyHope
  • 1,173
  • 1
  • 10
  • 19
0

I would suggest testing to see if the JSON.Net serializer is capable of serializing your type.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
0

"exited with code 0" means the program exited gracefully. Thus, it might be the caller of Post<T> or even above callers determine that it was time to end the program. If you are familiar with debugging tools such as WinDbg, you can set native breakpoints at ntdll functions to further diagnose the case, but normally you just need to review your code base.

Lex Li
  • 60,503
  • 9
  • 116
  • 147