Xamarin Forms, Autodesk Forge Access Token

In the previous posts, we went through each platform, looking at how we implement deep linking for each of the platforms. At the end of the deep link flow, we have arrived back within our portable Application object with a URL to process. This URL has a response code at the end that we have to parse out and send back to Forge to get our access and refresh tokens.

This is pretty easy, something like this works:


private string GetResponseCodeFromUrl(string redirectUrl)
{
    string codeParameter = "?code=";
    int pos = redirectUrl.IndexOf(codeParameter);
    string code = redirectUrl.Substring(pos + codeParameter.Length);
    return code;
}

After that we post a REST call to “https://developer.api.autodesk.com/authentication/v1/gettoken”. Inside of the content of the post call, we need to add a string with all of our app keys and codes, in a similar fashion to how we started off the whole authentication process in the first post of the series. The string content looks like this and should be all on one line.

var content = new StringContent($"client_id={ClientId}&client_secret={ClientSecret}&grant_type=authorization_code&code={ResponseCode}&redirect_uri={CallbackUrl}");

See the above link for an explanation of the ClientId, ClientSecret and redirect_uri. The ReponseCode is simply the code that we retrieved using the above GetResponseCodeFromUrl function above.


private AuthData AuthorizationData { get; set; }

public async Task<bool> GetAccessTokenAsync(string redirectUrl)
{
    ResponseCode = GetResponseCodeFromUrl(redirectUrl);
    using (HttpClient client = new HttpClient())
    {
        client.DefaultRequestHeaders.Clear();
        using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://developer.api.autodesk.com/authentication/v1/gettoken"))
        {
            request.Content = new StringContent($"client_id={ClientId}&client_secret={ClientSecret}&grant_type=authorization_code&code={ResponseCode}&redirect_uri={CallbackUrl}");
            request.Content.Headers.ContentType = 
                new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            using (HttpResponseMessage response = await client.SendAsync(request))
            {
                string data = await response.Content.ReadAsStringAsync();
                if (response.IsSuccessStatusCode)
                {
                    AuthorizationData = Deserialize<AuthData>(data);
                    return true;
                }
            }
        }
    }

    return false;
}

If all goes well, we end up getting a response with our authorization data. That structure looks like this:

public class AuthData
{
    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("expires_in")]
    public int ExpiresInMinutes { get; set; }

    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }

    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    public DateTime DateGranted { get; set; }

    public AuthData()
    {
        DateGranted = DateTime.Now;
    }
}

I am using Json.NET as my deserializer and am using the attributes to redirect the parsed data into the properties that I want. I think pretty much everyone uses Json.NET, but if it is the first you have heard about it, it is definitely worth your time to look at. Important properties above are:

  • AccessToken: use this for all of your Forge requests so that Forge knows you are authenticated.
  • RefreshToken: the access token will expire. You use the refresh token to request a new one without forcing the user to re-authenticate.
  • ExpiresIn: how many minutes before the access token expires.
  • DateGranted: not returned by Forge, but sets when the token was granted so that we can compute when it expires.
  • And that is about it! In the next post, we will look at refreshing the access token.

Xamarin Dev Days Lab – Prism Step 3

Introduction

In our last post, we set up the view model for the SpeakersPage and made use of the built in view model functionality included in Prism. We setup a base view model for our app to contain common functionality. The SpeakersViewModel class has the implementation code for retrieving the list of speakers embedded in the view model itself. Fine for a demo, but in a real app, we would be better served by moving this functionality out and using it via an interface. By implementing the functionality as an interface, we will be able to reuse the code in other view models. Since the SpeakersPageViewModel only knows it via the interface, we will also be able to mock the service with known values for use in unit tests, without changing the view model. And we can use the Prism framework and the dependency injection that is built in to make this easier. So lets take a look at this.

The Interface

The first thing we want to do is look at the functionality that is currently in our view model class. All it is doing is calling a web api to return a list of speakers. That seems pretty straight forward. Let’s start our interface with that:


public interface ISpeakersService
{
    Task<List<Speaker> GetAllSpeakersAsync();
}

Implementing will be easy: we already have all the code that we need in the view model from the demo app:


public class SpeakersService : ISpeakersService
{
    public async Task<List<Speaker>> GetAllSpeakersAsync()
    {
        using (var client = new HttpClient())
        {
            //grab json from server
            var json = await client.GetStringAsync(
                "http://demo4404797.mockable.io/speakers");

             //Deserialize json
             var items =
                JsonConvert.DeserializeObject<List<Speaker>>(json);
             return items;
        }
    }
}

//

From above, you can see that we have just moved all of the implementation code from the view model into a separate service object. So how do we start using this new code in our SpeakersViewModel?
The first thing we need to do is register this service in our App object. Remember that we are registering via an interface: this means we can change out the implementation at any time.
Here is the RegisterTypes function in the App object updated to register the service:


protected override void RegisterTypes()
{
    Container.RegisterType
        <Services.ISpeakersService, Services.SpeakersService>();
    Container.RegisterTypeForNavigation
        <View.SpeakersPage, ViewModel.SpeakersViewModel>();
}

Next we need to refactor the SpeakersViewModel: we will add the interface to the view model constructor and change the GetSpeakersAsync to call the interface to retrieve the speakers data:


public class SpeakersViewModel : BaseViewModel
{
    private Services.ISpeakersService _speakersService = null;

    public SpeakersViewModel(Services.ISpeakersService speakersService)
        : base()
    {
        _speakersService = speakersService;
    }

    /// other parts of the view model go here
    /// now lets look at GetSpeakers ...
    private async Task GetSpeakers()
    {
        if (IsBusy)
            return;

        Exception error = null;
        try
        {
            IsBusy = true;

            var items =
                await _speakersService.GetAllSpeakersAsync();
            Speakers.Clear();

            foreach (var item in items)
                Speakers.Add(item);
        }
        catch (Exception ex)
        {
            error = ex;
        }
        finally
        {
            IsBusy = false;
        }

        if (error != null)
            await Application.Current.MainPage.DisplayAlert(
                "Error!",
                error.Message,
                "OK");
    }

}

So what do we have above? All of a sudden the ViewModel has a dependency on ISpeakersService. But we weren’t creating the view model in the first place: instead, Prism and the AutoWireViewModel attached property (see the previous blog post) are creating the view model for us and attaching it to the page. When Prism does this, it uses the container that was selected (step 01 blog) to create the view model and all the dependencies that are required for the view model, and it does this via reflection and then looking at what you specified in the App.RegisterTypes method. I hope that you can see that you can change up the implementation details of the interface without ever affecting the view model itself. You can even unit test your view model by mocking the service.

Now the view model just makes a call to retrieve the speakers. It has no idea if the speaker are read from a web api, a database, a file or even from memory! It just knows to make the call and it will get the data.

I really want to emphasize this: the view model knows nothing. It has no dependency on any implementation and you can change that around as you see fit! In fact, I am going to change the code of the SpeakersService implementation. I captured the json payload that was returned from the web api and saved it as a constant in the implementation. Now instead of calling out to the web api, I just return the json payload directly, and now for testing, everything is much quicker. And as mentioned earlier, using these known values, I can use this implementation for unit testing of the view model.


public class SpeakersService : ISpeakersService
{
    /// you can see this actual string value in the GitHub repo
    /// under step 03
    private const string JsonResponse =
        "...json response string captured from web api";

    public async Task<List<Speaker>> GetAllSpeakersAsync()
    {
        var items =
            JsonConvert.DeserializeObject<List<Speaker>>(JsonResponse);
        return items;
    }
}

Recap

We have taken the next step in making the dev days app a little more production worthy. We took out the implementation of our speakers service away from the view model, defined it as an interface and injected that into our view model. We used the dependency injection that is built into Prism to inject the implementation of the service into the view model. And then for fun (and quicker testing), we changed the implementation of the interface to serve up the results from a json payload that had been captured previously. Now we can do testing much quicker.

All of this code can be found in the Step03 portion of the repository. Make sure you check out the two different implementations of ISpeakersService contained in the SpeakersService.cs file and how they could be registered in App.cs.

The next step will be to add navigation to the app so we can see the details of a selected speaker.

XF – Setup your App and Emulator

My computer was having some issues and I had to rebuild it. Luckily with Windows 10, this has never been a faster process. I make heavy use of Visual Studio team services, GitHub and OneDrive so backups are pretty easy too.

One thing I was struggling restoring was the capability of debugging my Android Xamarin Forms app in the Visual Studio emulator. Every time I started it up, it would immediately stop. Looking at the error messages in the debug output showed messages around the mscorlib.dll.so library.

All credit to this fix goes to Joost van Schaik and his post. As luck would have it, this is how I fixed it the first time, I just couldn’t remember it!

First thing is change your android options. Right click on your “droid” project and select “Properties”. Click on “Android Options” and make sure that “Use Fast Deployment (debug mode only)” is unchecked.

fastdeployment

Next you need to go into your emulator settings and fix up the processor settings. Click on the start menu button and type “hyper” and select “Hyper-V Manager”.

Right-click on the desired emulator and select settings:

hypervmanager

It’s a little hard to see, but under the context menu, you can see KitKat which is the emulator that I have been using. Settings should give you the following screen. Expand the processor node, click on “Compatibility” and make sure “Migrate to a physical computer with a different processor version” is checked. Note that you will only be able to do this if the emulator isn’t running.

emulator-processor-compat

And that was it. Once I made these two changes, I was able to debug in Visual Studio once again.

Hope you find this helpful and that by doing this post, I will remember the next time I need to rebuild my dev environment! For links to more information on these settings, I would suggest checking out Joost’s post on this subject.

 

Xamarin Forms Maps Bits

I ran across a couple of small issues tonight with my work with the Xamarin Forms Map, and it had to do with the precision of the values that I was using for the Center property that I setup in my previous post.

Normally in the Android emulator with Visual Studio, it has a preset starting location. For my app, I wanted something a little closer to home. To get the values for the MapSpan object, I was just outputting the values for the fields from the Center property that I had setup to figure out where I wanted to start from.

When I used those values as my initial start point for the map, I was putting in the full precision that the Visual Studio debugger was showing, approximately 15 digits after the decimal place. When I started forcing these values in, the map wouldn’t update its position.

I then started to play around with the location services in the emulator and the map would update in response to those values. Looking at the values displayed by the emulator, they only used 4 digits. I made the change and everything started working again. Assuming I am in the view model and am using the attached property to bind to set the center point of the map, this didn’t work for me:


// underlying Map.MoveToRegion call doesn't do anything
Center = new MapSpan
(
	new Position(48.0111563131213188, -122.0096835170062306),
	0.0096835170062306,
	0.0111563131213188
);

Instead, try using it like this:


// underlying Map.MoveToRegion call now works
Center = new MapSpan
(
	new Position(48.0111, -122.0096),
	0.0096,
	0.0111
);

I have yet to go looking at why this is the case but it seems likely that the map control can only handle that level of accuracy. If you are finding that you can’t seem to control what the map is displaying, check out the precision of the values in the MapSpan object. And if anyone reading this knows for sure what is happening here, feel free to chime in.

I will be attending a Xamarin dev workshop at Microsoft Vancouver, perhaps there will be someone there that can answer this definitely.

Hope that helps.

Xamarin Forms Map Center

Problem:

I have been working on an app in Xamarin, with the goal of being able to deploy to UWP, Android and IOS. This is my first real effort with Xamarin, and the first time publishing IOS and Android to their respective stores. Actually, this is my first IOS app ever! I still need to get on to Craigslist and find a reasonably priced Mac Mini so that I can build the IOS app.

Some app background: it makes use of the map control. My needs aren’t too difficult, but I need to know what the map control is displaying at any given moment. Specifically, I need the latitude and longitude of the map center. At least at this point, my app doesn’t need to worry about location tracking.

I am going to use Xamarin forms and take advantage of the cross platform UI. I also want to make use of the MVVM pattern and the data binding associated with XAML.I will of course use my favorite MVVM framework: Prism (I am going to do a series on Prism and UWP and a series on Prism and Xamarin Forms as well at some point). All of this sounds great: but unfortunately the map center data structure isn’t exposed as a bindable property, so we can’t use it directly in our view model.

Well, since every C#/XAML blog person needs an attached property post, that is what I decided to do. I am not sure that it is the best solution, but I can say that it seems to be working for me right now. Look for an update on this post if it doesn’t!

Solution:

I decided I wanted two properties. One that turned the tracking on and off and one that stored the information about what the map was viewing.

Attached properties are all kind of the same, so first we will just setup the basics (if you need a bit of a refresher on attached properties, check out the Xamarin docs):

  • Creation
  • Getter/Setter
  • Change event
public static class MapCenterProperty
{
	public static readonly BindableProperty CenterProperty =
		BindableProperty.CreateAttached(
			"Center",
			typeof(MapSpan),
			typeof(MapCenterProperty),
			null,
			propertyChanged: OnCenterChanged);

	public static MapSpan GetCenter(BindableObject view)
	{
		return (MapSpan) view.GetValue(CenterProperty);
	}

	public static void SetCenter(
		BindableObject view, MapSpan mapSpan)
	{
		view.SetValue(CenterProperty, mapSpan);
	}

	private static void OnCenterChanged(
		BindableObject view, object oldValue, object newValue)
	{
	}

	public static readonly BindableProperty TrackCenterProperty =
		BindableProperty.CreateAttached(
			"TrackCenter",
			typeof(bool),
			typeof(MapCenterProperty),
			false,
			propertyChanged: OnTrackCenterChanged);

	public static bool GetTrackCenter(BindableObject view)
	{
		return (bool) view.GetValue(TrackCenterProperty);
	}

	public static void SetTrackCenter(
		BindableObject view, bool value)
	{
		view.SetValue(TrackCenterProperty, value);
	}

	private static void OnTrackCenterChanged(
		BindableObject view, object oldValue, object newValue)
	{
	}
}

So let’s take a look at the TrackCenterProperty first. This is the one that is used to toggle the tracking off and on. The important stuff happens in the OnTrackCenterChanged event: it sets up the tracking. If the old value is false and the new value is true, start tracking. Stop tracking if the reverse is true.

Now it would be great if the Map control had an event that fired when the view of the map changed, but it doesn’t. So that is a bit of an issue. Luckily there is a bit of a hack we can use. We are interested in when the “VisibleRegion” property changes. So we are going to subscribe to the “PropertyChanged” event instead. If the name of the property being changed is “VisibleRegion”, we want to know about it.

Let’s update the OnTrackCenterChanged method from up above to subscribe and unsubscribe depending on the value of TrackCenter. It could look like the following:


private static void OnTrackCenterChanged(
	BindableObject view, object oldValue, object newValue)
{
    Map map = view as Map;
    if (map == null)
        return;

    bool ov = (bool) oldValue;
    bool nv = (bool) newValue;

    if (ov && !nv)
    {
        /// was true, now false, unsubscribe
        map.PropertyChanged -= OnMapPropertyChanged;
    }
    else if (!ov && nv)
    {
        /// was false, now true, subscribe
        map.PropertyChanged += OnMapPropertyChanged;
    }
}

All we are doing is subscribing or unsubscribing to the PropertyChanged event depending on the value of TrackCenter. Below is the event handler for that event. The only thing it really does is check to see if it is the VisibleRegion property being changed and if so, update the value of the CenterProperty.


private static void OnMapPropertyChanged(
	object sender, PropertyChangedEventArgs a)
{
    Map map = sender as Map;
    if (map == null)
        return;

    if (a.PropertyName == "VisibleRegion"
        && map.VisibleRegion != null)
    {
        Debug.WriteLine(&quot;SetCenter&quot;);
        map.SetValue(CenterProperty, map.VisibleRegion);
    }
}

Now all we have to do is setup the OnCenterChanged event. The only thing we have to be concerned about is giving ourselves a bit of fuzziness on whether the center point is changed enough to update the map, otherwise I found that the center point property was being updated too often.

private static void OnCenterChanged(
    BindableObject view, object oldValue, object newValue)
{
    var map = view as Map;
    if (map == null)
        return;

    MapSpan newview = newValue as MapSpan;
    MapSpan oldView = oldValue as MapSpan;

    if (newview != null &&
        !Util.MapSpanHelper.IsEqual(oldView, newview))
    {
        map.MoveToRegion(newview);
        SetCenter(view, newview);
    }
}

And the helper function for checking if the MapSpan has changed enough:

public static class MapSpanHelper
{
    public static bool IsEqual(double d1, double d2)
    {
        double dif = Math.Abs(d1 * 0.00001);
        return (Math.Abs((d1 - d2)) <= dif);
    }

    public static bool IsEqual(MapSpan ms1, MapSpan ms2)
    {
        if (ms1 == null && ms2 == null)
            return true;
        else if (ms1 == null || ms2 == null)
            return false;
        else if (
            IsEqual(ms1.Center.Latitude, ms2.Center.Latitude)
            && IsEqual(ms1.Center.Longitude, ms2.Center.Longitude)
            && IsEqual(ms1.LatitudeDegrees, ms2.LatitudeDegrees)
            && IsEqual(ms1.LongitudeDegrees, ms2.LongitudeDegrees))
            return true;
        else
            return false;
    }
}

You can adjust the fuzziness as appropriate.

Finally, we can setup our XAML and view model. Remember to add the namespaces. The MapCenterProperty class exists in the “Demo.Views” assembly.


xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"

xmlns:loc="clr-namespace:Demo.Views;assembly=Demo"

<maps:Map MapType="Street" loc:MapCenterProperty.TrackCenter="True" loc:MapCenterProperty.Center="{Binding Center,Mode=TwoWay}">

</maps:Map>

And the view model:


/// BindableBase provided by Prism, implements the
/// INotifyPropertyChanged interface for the view model
/// and some helper functions
public class DemoViewModel : BindableBase
{
    // ...

    private MapSpan _center = null;
    public MapSpan Center
    {
        get { return _center; }
        set { SetProperty<MapSpan>(ref _center, value); }
    }
}

And there we have it. We now have the viewable region of the map control bound to our view model. From within the view model we can change what is being shown on the map simply by setting the Center property. In the case of my app, I am also going to make use of the GeoLocator plugin from James Montemagno to provide some pretty nice location services to go with the maps in my app.

Hopefully you found this useful.