0

Using the Template Studio extension for Visual Studio, I generated a project solution base and am now attempting to interject the app load process with a HTTP request before proceeding the render the page view.

App.xaml.cs

using System;

using Braytech_3.Services;

using Windows.ApplicationModel.Activation;
using Windows.Storage;
using Windows.UI.Xaml;

namespace Braytech_3
{
    public sealed partial class App : Application
    {
        private Lazy<ActivationService> _activationService;

        private ActivationService ActivationService
        {
            get { return _activationService.Value; }
        }

        public App()
        {
            InitializeComponent();

            APIRequest();

            // Deferred execution until used. Check https://msdn.microsoft.com/library/dd642331(v=vs.110).aspx for further info on Lazy<T> class.
            _activationService = new Lazy<ActivationService>(CreateActivationService);
        }

        protected override async void OnLaunched(LaunchActivatedEventArgs args)
        {
            if (!args.PrelaunchActivated)
            {
                await ActivationService.ActivateAsync(args);
            }
        }

        protected override async void OnActivated(IActivatedEventArgs args)
        {
            await ActivationService.ActivateAsync(args);
        }

        private async void APIRequest()
        {
            //Create an HTTP client object
            Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();

            //Add a user-agent header to the GET request. 
            var headers = httpClient.DefaultRequestHeaders;

            Uri requestUri = new Uri("https://json_url");

            //Send the GET request asynchronously and retrieve the response as a string.
            Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
            string httpResponseBody = "";

            try
            {
                //Send the GET request
                httpResponse = await httpClient.GetAsync(requestUri);
                httpResponse.EnsureSuccessStatusCode();
                httpResponseBody = await httpResponse.Content.ReadAsStringAsync();

                APITempSave(httpResponseBody);

            }
            catch (Exception ex)
            {

            }
        }

        private async void APITempSave(string json)
        {
            StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;

            if (await tempFolder.TryGetItemAsync("APIData.json") != null)
            {
                StorageFile APIData = await tempFolder.GetFileAsync("APIData.json");
                await FileIO.WriteTextAsync(APIData, json);
            }
            else
            {
                StorageFile APIData = await tempFolder.CreateFileAsync("APIData.json");
                await FileIO.WriteTextAsync(APIData, json);
            }

        }

        private ActivationService CreateActivationService()
        {
            return new ActivationService(this, typeof(Views.VendorsPage), new Lazy<UIElement>(CreateShell));
        }

        private UIElement CreateShell()
        {
            return new Views.ShellPage();
        }
    }
}

I think what I need to do is call _activationService = new Lazy<ActivationService>(CreateActivationService); once APITempSave() has been called but I am unsure of how to do so and what best practices are.

Any guidance would be greatly appreciated!

Muhammad Touseef
  • 4,357
  • 4
  • 31
  • 75
Tom Chapman
  • 433
  • 7
  • 15
  • If the API request fails, is that a problem for your service activation? At the moment you're hiding any errors from this step, and (as I think is the basis for your question, correct me if I'm wrong), you're not waiting for the request to complete before proceeding, so there's a potential timing issue. – ProgrammingLlama Oct 09 '18 at 02:24
  • open a issue on github repo of template studio – Muhammad Touseef Oct 09 '18 at 02:41
  • @John that's true but assume the request is successful: i'm asking how to call one function after another completes – Tom Chapman Oct 09 '18 at 02:47
  • 1
    @touseefbsb this isn't an issue with template studio – Tom Chapman Oct 09 '18 at 02:47

1 Answers1

1

After further investigation and familiarisation with the generated solution, as well as additional Googling of await, async, and Tasks<>, I was able to implement the request as a service alongside items such as ThemeSelector, and ToastNotifications.

The ThemeSelector is one of the first things to be called in order to determine light and dark theme mode for the current user, so I was able to model my service around it and call it at the same time.

This is obviously very specific to the code that template studio generates, but some concepts are shared and should anyone else look for similar answers in the future maybe they'll find this.

APIRequest.cs (Service)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;

namespace Braytech_3.Services
{
    public static class APIRequest
    {

        internal static async Task Request()
        {
            //Create an HTTP client object
            Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();

            //Add a user-agent header to the GET request. 
            var headers = httpClient.DefaultRequestHeaders;

            Uri requestUri = new Uri("https://json_url");

            //Send the GET request asynchronously and retrieve the response as a string.
            Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
            string httpResponseBody = "";

            try
            {
                //Send the GET request
                httpResponse = await httpClient.GetAsync(requestUri);
                httpResponse.EnsureSuccessStatusCode();
                httpResponseBody = await httpResponse.Content.ReadAsStringAsync();

                await APITempSave(httpResponseBody);

            }
            catch (Exception ex)
            {

            }
        }

        internal static async Task APITempSave(string json)
        {
            StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;

            if (await tempFolder.TryGetItemAsync("APIData.json") != null)
            {
                StorageFile APIData = await tempFolder.GetFileAsync("APIData.json");
                await FileIO.WriteTextAsync(APIData, json);
            }
            else
            {
                StorageFile APIData = await tempFolder.CreateFileAsync("APIData.json");
                await FileIO.WriteTextAsync(APIData, json);
            }

        }
    }
}

ActiviationService.cs (originally called by App.xaml.cs)

private async Task InitializeAsync()
{
    await ThemeSelectorService.InitializeAsync();
    await APIRequest.Request();
}
Tom Chapman
  • 433
  • 7
  • 15