0

I am trying to send a http web request from a background agent. The code is as below. The json_Callback never gets triggered and my request doesn't reach the server. I have done all the exception handling and none of them get triggered.

How to send a web request in the background agent?

    protected override void OnInvoke(ScheduledTask task)
    {
        string toastMessage = "Testing Push running.";
        ShellToast toast = new ShellToast();
        toast.Title = "Background Agent Sample";
        toast.Content = toastMessage;
        toast.Show();

        try
        {
            string token = "no token";
            appSettings.TryGetValue("newToken", out token);
            toastMessage = "New Push running.";
            toast = new ShellToast();
            toast.Title = "Background Agent Sample";
            toast.Content = token;
            toast.Show();

            if (!String.IsNullOrEmpty(token))
                postTokenToServer(token);

            _event = new ManualResetEvent(false);
            _event.WaitOne();
        }
        catch (Exception e)
        {
            toastMessage = e.Message;
            toast = new ShellToast();
            toast.Title = "a";
            toast.Content = toastMessage;
            toast.Show();
        }

      #if DEBUG_AGENT
        ScheduledActionService.LaunchForTest(
                       task.Name, TimeSpan.FromSeconds(1));
      #endif
        toast = new ShellToast();
        toast.Title = "task complete";
        toast.Show();

        NotifyComplete();
    }



    private void postTokenToServer(string token)
    {
        ShellToast toast = new ShellToast();
        toast.Title = "is net available";
        toast.Content = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable().ToString();
        toast.Show();

        if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
        {
            HttpWebRequest req = HttpWebRequest.Create(new Uri(BASE + "/account/device")) as HttpWebRequest;
            req.Headers["Cookie"] = "user=" + appSettings["token"] + ";uid=" + (string)appSettings["uid"];

            toast.Title = "Cookies token";
            toast.Content = (string)appSettings["token"];
            toast.Show();
            toast.Title = "uid";
            toast.Content = (string)appSettings["uid"];
            toast.Show();

            req.Method = "POST";
            req.ContentType = "application/json";
            req.BeginGetRequestStream(new AsyncCallback(setParams_Callback), req);
        }
        else
            _event.Set();
    }

    private void setParams_Callback(IAsyncResult result)
    {
        string uri = "no token";
        appSettings.TryGetValue("newPushToken", out uri);
        var req = (HttpWebRequest)result.AsyncState;
        Stream postStream = req.EndGetRequestStream(result);

        JObject data = new JObject();
        data.Add("dev_token", uri);
        data.Add("dev_type", "windows");

        ShellToast toast = new ShellToast();
        toast.Title = "Posting Now";
        toast.Content = data.ToString(Newtonsoft.Json.Formatting.None);
        toast.Show();

        using (StreamWriter sw = new StreamWriter(postStream))
        {
            string json = data.ToString(Newtonsoft.Json.Formatting.None);
            sw.Write(json);
        }
        postStream.Close();

        try
        {
            req.BeginGetResponse(new AsyncCallback(json_Callback), req);
        }
        catch(Exception e)
        {
            toast.Title = "Posting Error";
            toast.Content =e.Message;
            toast.Show();
            _event.Set();
        }

        toast.Title = "Posted";
        toast.Content = DateTime.UtcNow.ToShortTimeString();
        toast.Show();
    }

    private void json_Callback(IAsyncResult result)
    {
        ShellToast toast = new ShellToast();
        toast.Title = "completed";
        toast.Show();
        _event.Set();
    }
alfah
  • 2,077
  • 1
  • 31
  • 55
Milan Aggarwal
  • 5,104
  • 3
  • 25
  • 54
  • 1
    `_event.WaitOne();` will freeze the current thread you're waiting on -so it will never complete. Personally, I'd re-write the `postTokenToServer` method using async/await and use `WebClient()`, cleaner and less code. – Neil Turner Jul 24 '13 at 12:24
  • thats what i want right? I dont want the main bg task thread to exit before the response is received. And why should a webclient be used for webrequest task? – Milan Aggarwal Jul 25 '13 at 05:49
  • using `WebClient` would eliminate the need for callbacks and simplify the code, it's also awaitable – Neil Turner Jul 25 '13 at 13:06

1 Answers1

0

Not sure if this will help you or not, but here's how I make HTTP requests in my background agent:

Making the call using WebClient (this was written before the very nice HttpClient NuGet package became available):

    public async Task<string> GetArrivalsAsync( IEnumerable<int> locations )
    {
        var request     = new WebClient();
        var requestUri  = GetArrivalsRequestUri( locations );
        var response    = await request.DownloadStringTask( requestUri );

        return response;
    }

Note that I use the async/await keywords here which greatly simplifies writing asynchronous code. Most of the work is done in this extension method to WebClient. I can't take credit for the extension method, but it's been a while and I can't recall where I found it (although it was probably here on StackOverflow):

/// <summary>
/// The WebClientExtensions class provides extension methods for the <see cref="System.Net.WebClient"/> class.
/// </summary>
public static class WebClientExtensions
{
    /// <summary>
    /// This extension method is used to asynchronously download data from a URI
    /// and return that data in the form of a string.
    /// </summary>
    /// <param name="webClient">The <see cref="System.Net.WebClient"/> instance used to perform the download.</param>
    /// <param name="uri">The URI to download data from.</param>
    /// <returns>The <see cref="Task"/> used to perform the operation.</returns>
    public static Task<string> DownloadStringTask( this System.Net.WebClient webClient, Uri uri )
    {
        if ( uri == null )
        {
            throw new ArgumentNullException( "uri" );
        }

        var tcs = new TaskCompletionSource<string>();

        webClient.DownloadStringCompleted += ( s, e ) =>
            {
                if ( e.Error != null )
                {
                    tcs.SetException( e.Error );
                }
                else
                {
                    tcs.SetResult( e.Result );
                }
            };

        webClient.DownloadStringAsync( uri );
        return tcs.Task;
    }
}
Mats Lannér
  • 1,236
  • 7
  • 6