0

I've been scratching my head on this for a while. I have no clue where this exception is being thrown. Where the heck am I supposed to catch this exception? It's a System.Net.WebException. I guess I'm just not getting Task and async/await. I understand I'm creating other threads, which is great and all, but where do I handle the exception?

The remote server returned an error: (403) Forbidden.

Here is the code:

public async void sendRequest(string database, string table, string where, bool isPost, int deviceType)
{
    string urlQuery = Constants.URL_QUERY + database + "/" + table + "?" + where;

    Debug.WriteLine("URL Query: " + urlQuery);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlQuery);
    request.Method = isPost ? "POST" : "GET";
    request.ContentType = "application/json";

    try
    {
        Debug.WriteLine("getting response");
        WebResponse response = await makeAsyncRequest(request);
        Debug.WriteLine("response obtained");
        finishRequest(response);
    }
    catch (WebException e)
    {
        Debug.WriteLine("WebException caught");
    }
}

private async static Task<WebResponse> makeAsyncRequest(HttpWebRequest req)
{
    Task<WebResponse> task = Task.Factory.FromAsync<WebResponse>(req.BeginGetResponse, req.EndGetResponse, null);

    await task.ContinueWith(t =>
    {
        if (t.IsFaulted)
        {
            Debug.WriteLine("It's faulted.");
            t.Exception.Handle((x) =>
            {
                if (x is WebException)
                {
                    Debug.WriteLine("It's a web exception");
                    return true;
                }
                Debug.WriteLine("Exception?: " + x);
                return false;
            });
        }
    });
    Debug.WriteLine("returning task");
    return task.Result;
}

private static void finishRequest(WebResponse response)
{
    Debug.WriteLine("finishRequest called");
}

Here is what I see in my Output window:

2014-10-07 14:05:05.104 FormsTemplateiOS[1568:53280] getting response
[0:] getting response
Thread started:  #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Thread started: <Thread Pool> #7
Thread started:  #8
[0:] 
2014-10-07 14:05:05.681 FormsTemplateiOS[1568:53326] It's faulted.
[0:] It's faulted.
[0:] 
2014-10-07 14:05:05.804 FormsTemplateiOS[1568:53326] It's a web exception
[0:] It's a web exception
Unhandled Exception:

System.Net.WebException: The remote server returned an error: (403) Forbidden.

Unhandled Exception:
System.Net.WebException: The remote server returned an error: (403) Forbidden.
  at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x0033b] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.0.0.63/src/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1718 
  at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00165] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.0.0.63/src/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1485 
The program 'Mono' has exited with code 0 (0x0).
Debugging session ended.

Edit:

I updated makeAsyncRequest(HttpWebRequest) per Stephen Cleary suggestion. I'm still having the same problem.

private async static Task<WebResponse> makeAsyncRequest(HttpWebRequest req)
{
    Task<WebResponse> task = Task.Factory.FromAsync<WebResponse>(req.BeginGetResponse, req.EndGetResponse, null);
    try
    {
        return await task;
    }
    catch (WebException e)
    {
        Debug.WriteLine("It's a WebException");
    }
    catch (Exception e)
    {
        Debug.WriteLine("Other Exception");
    }
    return null;
}

Output window:

2014-10-07 14:32:08.385 FormsTemplateiOS[1588:57008] getting response
[0:] getting response
Thread started:  #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Thread started: <Thread Pool> #7
Thread started:  #8
Unhandled Exception:

System.Net.WebException: The remote server returned an error: (403) Forbidden.

Unhandled Exception:
System.Net.WebException: The remote server returned an error: (403) Forbidden.
  at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x0033b] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.0.0.63/src/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1718 
  at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00165] in ///Library/Frameworks/Xamarin.iOS.framework/Versions/8.0.0.63/src/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1485 
The program 'Mono' has exited with code 0 (0x0).
Debugging session ended.
Jared Price
  • 5,217
  • 7
  • 44
  • 74
  • _. I have no clue where this exception is being thrown_ did you try to look at the StackTrace? – Selman Genç Oct 07 '14 at 19:04
  • Adding output to question. – Jared Price Oct 07 '14 at 19:06
  • Enable [Break when a exception is thrown](http://msdn.microsoft.com/en-us/library/d14azbfh.aspx). Debugger will stop right where the exception is thrown. Other option is inspect the StackTrace – Sriram Sakthivel Oct 07 '14 at 19:06
  • Tryto handle the [TaskScheduler.UnobservedTaskException-Event](http://msdn.microsoft.com/de-de/library/system.threading.tasks.taskscheduler.unobservedtaskexception(v=vs.110).aspx) to get more information – Jehof Oct 07 '14 at 19:09

1 Answers1

5

I understand I'm creating other threads, which is great and all

No, actually. You may want to read my async intro.

Also:

  • Avoid async void.
  • Use await instead of ContinueWith.

You may also find my async best practices article helpful.

private async static Task<WebResponse> MakeRequestAsync(HttpWebRequest req)
{
  Task<WebResponse> task = Task.Factory.FromAsync<WebResponse>(req.BeginGetResponse, req.EndGetResponse, null);
  try
  {
    return await task;
  }
  catch (WebException ex)
  {
    Debug.WriteLine("It's a web exception");
  }
  catch (Exception ex)
  {
    Debug.WriteLine("It's not a web exception.");
  }
}

As a final note, consider using HttpClient instead of HttpWebRequest. HttpClient was designed for async usage.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • If a Task isn't on a separate thread, then why is it part of System.Threading? – Jared Price Oct 07 '14 at 19:10
  • 3
    It's for historical reasons. `Task` was originally introduced as part of the Task Parallel Library, where it was mainly used to represent work to be executed on a thread. It has been repurposed for use as an arbitrary "asynchronous operation". – Stephen Cleary Oct 07 '14 at 19:12
  • I need to be able to set request headers and method to POST or GET. Can this be done with HttpClient? Scrolling through the properties and methods, I don't see anything that would allow this. – Jared Price Oct 07 '14 at 19:25
  • I tried this code. The same exception is still not being caught. I'll add my updated code to my question. – Jared Price Oct 07 '14 at 19:32
  • @JaredPrice: By "not caught" do you mean it's just being caught in the debugger? Because it will be caught by the `catch` at runtime. – Stephen Cleary Oct 07 '14 at 19:40
  • @JaredPrice: The request headers can be set via `DefaultRequestHeaders`, and the different method strings are exposed as different methods (`GetAsync`, `PostAsync`, etc). – Stephen Cleary Oct 07 '14 at 19:41
  • According to http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.defaultrequestheaders%28v=vs.118%29.aspx, HttpClient.DefaultRequestHeaders is read only. It only has get. – Jared Price Oct 07 '14 at 19:49
  • It's not being caught. If it was caught, I would get the debug message saying "It's a WebException". You can see that is not in my output. – Jared Price Oct 07 '14 at 19:56
  • @JaredPrice: If you still have "break on thrown exception", then it will break *before* it's caught. And `client.DefaultRequestHeaders.Accept.Add`. – Stephen Cleary Oct 07 '14 at 19:57
  • Ok, thanks for clarifying HttpClient.DefaultRequestHeaders. But I'm not sure I understand what you're saying about "break on thrown exception". – Jared Price Oct 07 '14 at 20:04
  • @JaredPrice: I mean [do you have these check boxes checked](http://msdn.microsoft.com/en-us/library/d14azbfh.aspx)? – Stephen Cleary Oct 07 '14 at 20:06
  • Thrown is unchecked for everything in Debug->Exceptions. So unless I'm not understanding what you're asking, I don't think that has anything to do with it. I also unchecked "User-unhandled" for System.Net.WebException for the heck of it and I'm still getting the same unhandled exception. – Jared Price Oct 07 '14 at 20:14
  • @JaredPrice: As a test, can you install `Nito.AsyncEx.AsyncDiagnostics` from NuGet? And you did get rid of the `async void`, right? – Stephen Cleary Oct 07 '14 at 21:07