23 October 2014

Making the Application Bar display on of top of the UI in Windows Phone 8.1 Store Apps

In Windows Phone 7, 8 and 8.1 Silverlight apps this is very easy: you just set the Opacity of the Application bar to any value less than 1 as described here, and the app does not reserve space for the app bar – it just displays the bar on top of the main UI like this:

image

The problem is, if you set the opacity of what is now called the CommandBar in Windows Phone 8.1 Store apps, the Application bar is translucent indeed - which you can see if you open it - but the apps still reserves space for it in it’s closed state:

image

The fix for this is surprisingly easy, but also pretty hard to find if you don’t know what you are looking for. In the end I got a tip by mail from my famous fellow MVP Rudy Huyn. You just add the following, not very obvious line of code to your app. I added it to my App.Xaml.cs, just before the line “Window.Current.Activate();”

 ApplicationView.GetForCurrentView().SetDesiredBoundsMode(
   ApplicationViewBoundsMode.UseCoreWindow);

Right. And then you get what you want (as is displayed in the first image). And once you enter this line of code into a search engine, then you find hits enough, dating back to even April. But well, that did not help me much. Hopefully this simple article will save someone else a fruitless seach ;)

To make this code compile, you will need to add a “using Windows.UI.ViewManagement;” on top of your file. And although it is in fact an article about code, I will skip the sample download app this time – for just one line of code it feels like a bit of overkill.

01 October 2014

Visualizing geofences as circles on the map in Universal Apps

Intro

If you tried to work with geofences, you may have encountered this problem. You want to have an easy way to show where the darn things are on the map, so you can test the application. This is actually pretty simple, building upon stuff to draw circles on Windows Phone 8 I wrote earlier.

What is important to know – there are now more or universally applicable objects to depict a location. The first one is BasicGeoposition – this is a struct – that basically only holds latitude, longitude and elevation. The second one is Geopoint. You create a Geopoint from a BasicGeoposition. This kind of wrapper class that allows for setting of some additional location settings – like how coordinates and height should be interpreted. I don’t think any of this stuff is really used yet, but I have the feeling Geopoint is going to get more important over time, and anyway as a GIS person I tend to go with the fullest set of location designation. But you might as just well use just BasicGeoposition as a way to pass on coordinates in a universal app.

Do the math!

This is essentially the same method as I wrote before, but adapted for Geopoint. Some other changes come from my former colleague Jarno Peschier, who in his typical way saw possibilities to optimize speed up the circle calculation code (and optimizations actually work – I tested).

using System;
using System.Collections.Generic;
using Windows.Devices.Geolocation;

namespace MappingUtilities
{
  public static class GeopointExtensions
  {
    private const double circle = 2 * Math.PI;
    private const double degreesToRadian = Math.PI / 180.0;
    private const double radianToDegrees = 180.0 / Math.PI;
    private const double earthRadius = 6378137.0;
    
    public static IList<Geopoint> GetCirclePoints(this Geopoint center,
                                   double radius, int nrOfPoints = 50)
    {
      var locations = new List<Geopoint>();
      double latA = center.Position.Latitude * degreesToRadian;
      double lonA = center.Position.Longitude * degreesToRadian;
      double angularDistance = radius / earthRadius;

      double sinLatA = Math.Sin(latA);
      double cosLatA = Math.Cos(latA);
      double sinDistance = Math.Sin(angularDistance);
      double cosDistance = Math.Cos(angularDistance);
      double sinLatAtimeCosDistance = sinLatA * cosDistance;
      double cosLatAtimeSinDistance = cosLatA * sinDistance;

      double step = circle / nrOfPoints;
      for (double angle = 0; angle < circle; angle += step)
      {
        var lat = Math.Asin(sinLatAtimeCosDistance + cosLatAtimeSinDistance * 
                            Math.Cos(angle));
        var dlon = Math.Atan2(Math.Sin(angle) * cosLatAtimeSinDistance, 
                              cosDistance - sinLatA * Math.Sin(lat));
        var lon = ((lonA + dlon + Math.PI) % circle) - Math.PI;

        locations.Add(new Geopoint(new BasicGeoposition { 
        Latitude = lat * radianToDegrees, Longitude = lon * radianToDegrees }));
      }
      return locations;
    }
  }
}

I think this is the Haversine formula but I am not sure and the point is – it gives list of points that, when drawn on a map, gives a reasonable approximation of a circle, where ever you draw it. And that’s what this is about. The radius is the radius in meters, and the numberOfPoints is still the number of points that is used to draw the polygon. For that’s what we are making – as long as there are enough points, our eyes will see this as a circle.

The method is implemented as an extension method to Geopoint, and while I was at it, I added a helper method for BasicGeoposition as well, which was not quite rocket science.

public static IList<Geopoint> GetCirclePoints(this BasicGeoposition center,
                              double radius, int nrOfPoints = 50)
{
  return new Geopoint(center).GetCirclePoints(radius, nrOfPoints);
}

Geofences you said sir?

So far, I have been mumbling only about coordinates – stuff I tend to talk about a lot – but how do I go from geofences to things on a map? Well, pretty easily, actually. It turns out that a geofence has a property Geoshape of type IGeoshape, but since a geofence can only be a circle right now, you can try to cast it to a Geocircle. And a Geocircle has a Center property of type BasicGeoposition, and a Radius property in meters. And that’s what we needed to use the GetCirclePoints extension method. So it’s actually pretty easy to define a new extension method

using System.Collections.Generic;
using Windows.Devices.Geolocation.Geofencing;
using Windows.Devices.Geolocation;

namespace MappingUtilities.Geofencing
{
  public static class GeofenceExtensions
  {
    public static IList<Geopoint> ToCirclePoints(this Geofence fence, 
      int nrOfPoints = 50)
    {
      var geoCircle = fence.Geoshape as Geocircle;

      if (geoCircle != null)
      {
        return geoCircle.Center.GetCirclePoints(geoCircle.Radius, nrOfPoints);
      }
      return null;
    }
  }
}

I always do the as-and-if-null check. I could have make a hard cast, but I am all for defensive programming.

Now the thing is, the GeofenceMonitor has a Geofences collection that can be used to add geofences (duh) but of course you can also retrieve them. And thus you can make yet another simple extension method to retrieve a list of list of points of your current GeoFenceMonitor

using System.Collections.Generic;
using System.Linq;
using Windows.Devices.Geolocation;
using Windows.Devices.Geolocation.Geofencing;

namespace MappingUtilities.Geofencing
{
  public static class GeofenceMonitorExtensions
  {
    public static IList<IList<Geopoint>> GetFenceGeometries(this GeofenceMonitor monitor)
    {
      return monitor.Geofences.Select( p=> p.ToCirclePoints()).ToList();
    }
  }
}

And since the GeofenceMonitor is a static class with a singleton instance, getting all the points of all the geofences in you app in a handy list by one simple call goes like this:

GeofenceMonitor.Current.GetFenceGeometries();

And by iterating over them, you can draw shapes on the map. The fun thing is, since we now have Universal Apps, you can define all this code in a PCL and use it both on Windows Phone and Windows ,and reference this as a Binary. Today. No need to wait for Windows 10. So I put these methods in a PCL called MappingUtilities. And because the current GeofenceMonitor is a singleton, you can use this code in some button method in your app to just get a quick list of the active geofences and draw them on a map, without having to retrieve data from your models or viewmodels, or however you choose to implement your logic.

But there is a tiny detail though. Bing Maps does not using Geopoint or BasicGeoposition, but still the Location class, and that does not exist on Windows Phone.

One more thing to extend

Since I was creating extension methods anyway, I made a new assembly, this time Windows specific, called MappingUtilities.Windows - I bet you did not see that one coming :) – and added the following two extension methods:

using System.Linq;
using Bing.Maps;
using System.Collections.Generic;
using Windows.Devices.Geolocation;

namespace MappingUtilities
{
  public static class PointHelpers
  {
    public static LocationCollection ToLocationCollection(
      this IList<Geopoint> pointList)
    {
      var locations = new LocationCollection();
      foreach (var p in pointList)
      {
        locations.Add(p.ToLocation());
      }
      return locations;
    }

    public static Location ToLocation(this Geopoint location)
    {
      return new Location(location.Position.Latitude, 
                          location.Position.Longitude);
    }
  }
}

And these you can simply use to quickly turn a Geopoint into a Location, or a list of Geopoints into a LocationCollection. How this is used is displayed in the demo solution.

Wrapping it up

The demo solution creates two geofences, and shows how the location of said fences can be displayed pretty easily by calling the GetFenceGeometries extension method, both on Windows Phone and Windows.

image image

The drawing on the map is done by a simple method that I won’t go into here. I wish to stress the fact that the creation of geofences is in the Shared portion of the app, as well as the facts that these geofences are pretty minimal – I just create them with the default settings - and that I don’t do anything with these geofences apart from creating them. The only thing what this app shows is how easy it is to display geofences using this extension methods, if you have geofences.

If you want to know more about using geofences in Universal Apps and how you could actually be doing something useful with them, please visit my talk on October 18th 2014 where I will be doing a session about this subject on the Lowland Windows Phone Hacker day. This day is organized in a joint effort by both the Dutch and Belgian developer communities in Tilburg, the Netherlands, a place very near the Belgian-Dutch border. Apart from great content - we also have some prizes you may be interested in

image

Just saying :)

27 August 2014

Simple workaround for “Design view is unavailable for x64 and ARM target platforms”

When you are developing for Windows Phone or Windows and you are faced with using a native component (for instance the Bing Maps control on Windows, or the SensorCore api on Windows Phone) you will loose your designers when you are testing, both in Visual Studio and in Blend, as they will only work for “AnyCPU”  or “x86” configurations.This is highly annoying, but there is a kind-of fix.

The trick is to create an extra configuration. I usually make a copy of “Debug”, which I call “DebugArm” I do this by right clicking on the solution, selecting “properties”, and then hit “Configuration Manager”

image

Then I make a copy of Debug, by selecting “New” in the “Configuration” drop down, and I make a copy of Debug, called DebugArm.

image

In that solution I set everything to ARM:

image

So far so good, and nothing new. Now select the Debug project configuration again in Visual Studio, hit “Save all” and compile. Then open the solution in Blend. You will notice of course the designers now work, but now you cannot deploy. Changing that configuration every time again is slow and cumbersome, and it won’t be picked up by Blend. So you have to restart that time and time again. This now, my friends, we will use to our advantage.

Go back to Visual Studio, select “DebugArm”. You can now deploy and test again, but your designers will of course go dead again. But like I said Blend does not pick up that configuration change. Apparently that is only read at startup. So that will keep the Debug configuration and the designer still will work! So now you can use Blend to do design changes, and Visual Studio to actually run and deploy, using two different configuration settings, without having to change al the time!

This switchemarole you have to do every time you start Visual Studio and Blend. Granted, it’s not ideal, but a lot less of a hassle than constantly having to change configurations, which is is slow, while now you only have to select a different Icon in the Task Bar. And this is how it should be done most of the time IMHO – Blend is for the UI, Visual Studio for code.

No code this time, as this is a tools-trick only post.

13 August 2014

Querying the Windows Phone 8.1 map when there are child objects over it

With the Windows Phone 8.1 SDK came (yet again) an improved Map Control. This brought, among other things, the MapIcon. In ye olde days, the map could only draw lines and polygons natively – when you had to draw icons you had to add child objects to the map itself, which were drawn by the UI thread and not by the map. This is slower and eats more resources.

imageThe new map still offers this possibility. And sometimes we need it, too, for a couple of reasons. First of all, a MapIcon can only display an image and an optional label. Second, MapIcons are drawn on the map using a ‘best effort’, which mean overlapping icons don’t get displayed at all and – worse – if you query the map, using the FindMapElementsAtOffset method, they are not found either.

So in some cases we just need to resort to drawing XAML elements by adding to the map’s Children collection – an option, which luckily has been improved tremendously as we now, for instance, can data bind these elements using the MapItemsControl, as explained by my smart fellow MVP Shawn Kendrot. Before 8.1, we needed the Windows Phone Toolkit for that.

But I noticed something very odd. I have been trained to use the MapTapped event to trap the location where the user tapped, as the Tapped event is being trapped by the map itself. It never fires. So I used MapTapped, and then FindMapElementsAtOffset to query the map;

But to my dismay I also discovered that the MapTapped event does not fire either when you tap on a location where a child object is displayed. Ergo – if you tap on the cross where the Windows Phone logo is displayed, nothing happens. So how am I to find out what’s underneath there?

After some trashing around I stumbled upon the answer – if you tap on a child element that’s on the map – not the MapTapped, but the Tapped event fires. “The event that never fires” comes to the rescue. In addition, the Tapped event on the child object itself fires. So I created the following method to query the map:

private void QueryMap(Point offset)
{
  foreach (var obj in MyMap.FindMapElementsAtOffset(offset))
  {
    Debug.WriteLine(obj.GetType());
  };
}
The regular method to trap MapTapped:
private void MyMap_OnMapTapped(MapControl sender, MapInputEventArgs args)
{
  Debug.WriteLine("MyMap.MapTapped occurred");
  QueryMap(args.Position);
}

And a method to trap Tapped when that occurs, and that also routes to the QueryMap method, with a little help from the GetPosition event method:

private void MyMap_OnTapped(object sender, TappedRoutedEventArgs e)
{
  Debug.WriteLine("MayMap.Tapped occurred");
  QueryMap(e.GetPosition(MyMap));
}

And because the events never fire simultaneously, you will see the map finds one PolyLine when you tap on a line just next to the symbol, will and it fill find two lines (the crossing of both) when you tap on the symbol- but never will you get a double hit from both events.

By attaching to the Tapped event of the Child object I can also detect if the symbol itself is tapped:

var childObj = new Image { 
  Source = new BitmapImage(new Uri("ms-appx:///Assets/wplogo.png")) };
MapControl.SetNormalizedAnchorPoint(childObj, new Point(0.5, 0.5));
MapControl.SetLocation(childObj, p5);
MyMap.Children.Add(childObj);
childObj.Tapped += ChildObj_Tapped;



void ChildObj_Tapped(object sender, TappedRoutedEventArgs e)
{
  Debug.WriteLine("ChildObj.Tapped occurred");
}

And thus we can find everything on the map, provided you attach the right methods to the right events. The MapTapped/Tapped combo of the map is an odd one but once you know how to do it – a few extra lines of code does it all.

A demo app demonstrating the whole concept can be found here.The only thing it does is write things to the debug console when you do something, so pay attention what happens there ;-)

06 August 2014

AngularJS + TypeScript: how to implement validation

Preface

AngularJs supports all kinds of simple client-side validation. The simplest is data-ng-required which basically says a UI element must be filled in before the form is valid. I am picking up where I left off in my previous post – I am going to make the the phone input screen have validation.

Adapting the view

First of all we are going to tweak the view a little. This is just standard AnguarJS stuff, nothing TypeScript specific here yet:

<div>
  <div>
    Phones
    <div data-ng-repeat="phone in listOfPhones">
      <div>Name: {{phone.name}}; screen size: {{phone.screenSize}}"</div>
    </div>
  </div>

  <button data-ng-click="phoneController.doLoadPhones()">Load phones from server</button>
  <br /><br />
  Add a new phone<br />
  <div data-ng-form="phoneform" class="css-form">
    <label for="name" style="width:40px">Name</label>
    <input id="name" type="text" data-ng-model="newPhone.name"
           data-ng-required="true" /><br />
    <label for="name" style="width:40px">Size</label>
    <input id="screensize" type="text" data-ng-model="newPhone.screenSize"
           data-ng-required="true" /><br />
    <button data-ng-click="phoneController.doSavePhone()"
            data-ng-disabled="!phoneController.canSave()">
      Save
    </button>
  </div>
</div>

I have underlined and written in red what is new:

  • A wrapper div with a form name and a css class
  • data-ng-required attribute, one on each field
  • A data-ng-disabled attribute on the button that will enable/disable it when the input is not valid.

Adapting the scope

Just like anormal AngularJS (based on JavaScript), the scope will now be extended with a property named “phoneform” – for that is how we called the form. So we need to adapt the IPhoneScope like this:

/// <reference path="../models/iphone.ts" />
module App.Scope {
    "use strict";

    export interface IPhoneScope {
        listOfPhones: Models.IPhone[];
        newPhone: Models.IPhone;
        phoneform: ng.IFormController
    }
}

And once again we now have the advantage of a typed object.

Adapting the controller

This is also very simple: we need to create the canSave method. So in the PhoneController we add:

public canSave(): boolean {
    return this.$scope.phoneform.$valid;
}

And that is basically most of what we need to do.

Adding some feedback css

Now to have some visual feedback to see if things are valid or not, we use (again) a standard AngularJS trick. In the view we have added the class “css-form” to the form. So we open the Site.css file in the content folder and add the following css:

.css-form input.ng-invalid.ng-dirty {
    background-color: #FA787E;
}

.css-form input.ng-valid.ng-dirty {
    background-color: #78FA89;
}

Testing the validation

If you run the app (after emptying your cache) you will notice you cannot click the save button initially:

image

If you enter phone name, the field will become greenish. If you type something in the screen size field and then delete it again, the field will become reddish, and the button is still disabled.

image

Only when both fields are filled in the save button is enabled

image

An interesting way to mess up validation – or a bug?

According to numerous samples I saw, you don’t need to write data-ng-required=”true”. Just entering data-ng-required (or plain ng-required) should work as well. It does – your field is invalid when it is empty. Trouble is, if you enter data and then delete it again, the field stays valid – and the form too, and you can hit the save button with one empty field. I have no idea if that is a bug in the version of AnguarJS I use, or if this recently has been changed – but please make sure you write data-ng-required=”true”

Demo solution can be found here

05 August 2014

AngularJS + TypeScript – using $resource to talk to a WebApi backend

Intro – multiple stacks to choose from

There are a number of ways to talk to a backend (i.e. communicate over JSON services) in Angular. I know at least of two built-in: the $http api, which basically gives you a bit raw, jQuery-like API, and the $resource API, which kind of builts on top of that, using a more formalized approach. Also, you can choose to forego the whole built-in stack and use something like Breezejs which has it own pros and cons. I used both successfully. And I don’t doubt there are more. But in this article I will concentrate on $resource.

Once again, I don’t claim ultimate wisdom nor do I claim this is the best way, but I describe a way that works and is complete.

Setting up the backend

I continue where I left off in my previous post, and proceed to add a model class in the Models folder. Mind you, this the folder in the root, not that in the app folder with TypeScript stuff in it. We are talking C#. Our application will be extended to maintain a list of phones.

namespace AtsDemo.Models
{
  public class Phone
  {
    public long Id { get; set; }

    public string Name { get; set; }

    public double ScreenSize { get; set; }
  }
}

imageThen add a WebApi controller in the Controllers folder. I right-clicked the Controllers folder, clicked “Add/Controller”, selected “Web API 2 Controller with read/write actions” and called it – very originally – “PhonesController”. I implemented only the Get and the Post method, to prove the communication actually works:

using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using AtsDemo.Models;

namespace AtsDemo.Controllers
{
  public class PhonesController : ApiController
  {
    private static List<Phone> phoneDb;

    private List<Phone> PhoneDb
    {
      get
      {
        if (phoneDb == null)
        {
          phoneDb = new List<Phone>
          {
            new Phone {Id = 1, Name = "Lumia 1020", ScreenSize = 4.5},
            new Phone {Id = 2, Name = "Lumia 1520", ScreenSize = 6.0},
            new Phone {Id = 3, Name = "Lumia 625",  ScreenSize = 4.7},
            new Phone {Id = 3, Name = "Lumia 930",  ScreenSize = 5.0}
          };
        }

        return phoneDb;
      }
    }
    // GET: api/Phones
    public IEnumerable<Phone> Get()
    {
      return PhoneDb;
    }

    // POST: api/Phones
    public void Post([FromBody]Phone value)
    {
      value.Id = PhoneDb.Max(p => p.Id) + 1;
      PhoneDb.Add(value);
    }
  }
}

As you can see this implements an ‘in memory database’ ;-) to list and store phones. To make sure WebApi honors the JavaScript convention of using camel casing, the following code needs to be added at the end of the Register method of the WebApi class in App_Start:

var jsonFormatter = 
  config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = 
  new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(
  new MediaTypeHeaderValue("text/html"));
The last statement is actually only to make WebApi default output JSON – this is not actually necessary, but it makes testing WebApi a bit easier. To get this to work, three extra usings will be necessary:
using System.Net.Http.Formatting;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Headers;

If your run the project and then change the url in http://localhost:3987/api/phones you get the following data:

[{"id":1,"name":"Lumia 1020","screenSize":4.5},{"id":2,"name":"Lumia 1520","screenSize":6.0},{"id":3,"name":"Lumia 625","screenSize":4.7},{T"id":3,"name":"Lumia 930","screenSize":5.0}]

This is easiest in Chrome, as it has no qualms about displaying raw JSON in the browser. In Internet Explorer it works as well, but IE insist on saving the file to disk, refusing it to display for security reasons. The backend now works.

Creating model and interface

If you have installed the Web Essentials 2013 for Update 2 as I recommended in the first part of this series you can now do something fun, although with such a little model not very useful yet:

  • Right-click Phone.cs
  • Select Web Essentials (all the way to the top)
  • The select “Create TypeScript Intellisense file. This will generate a file “Phone.cs.d.ts” with the following contents:
declare module server {
    interface Phone {
        id: number;
        name: string;
        screenSize: number;
    }
}
Which gives a nice skeleton that we can use. I don't like client side models sitting next to C# code, so I create a folder "models" in my "app" folder and moved this file over to that location (for some reason that does not work in the Solution Explorer; I used the Windows Explorer to do that). I addition, I renamed the file to Phone.cs, made a class of it and put the class inside the App.Models namespace, so the net result is:
module App.Models {
    "use strict"; 
     export class Phone {
        id: number;
        name: string;
        screenSize: number;
    }
}
Now this is where is gets a little complicated and it had me reeling some time. If you want to use a resource to get models from and to a backend, you will need to define a resource on an interface, not on a class. According to this Stack Overflow example – the only one I have been able to find, although it is parroted on several other places (up to and including the errors that were – and still are – in it) – we need two interfaces like this:
module App.Models {
    export interface IPhone extends ng.resource.IResource<IPhone> {
        id: number;
        name: string;
        screenSize: number;
    }

    export interface IPhoneResource extends
       ng.resource.IResourceClass<IPhone> {
    }
}

This works fine – as long as you never need a concrete implementation of IPhone. But if you do, and you make your Phone class implement IPhone like this:

 export class Phone implements Models.IPhone

You will be rewarded with a compilation error.

image

Simply because an IPhone now not only needs to implement it’s three properties but also the whole kit and caboodle that comes with being a resource. 

What I came up with was to define actually three interfaces. First, we define a simple interface for the object itself:

module App.Models {
    "use strict"; 
     export interface IPhone {
         id: number;
         name: string;
         screenSize: number;
    }
}

Then we define a simple interface that only extends a resource on IPhone. I define these in the “resources” folder (and namespace) as I like to keep related stuff together. First, I define a resource definition interface

/// <reference path="../models/iphone.ts" />
 module App.Resources {
    "use strict"; 
     export interface IPhoneResourceDef
     extends ng.resource.IResource<Models.IPhone> {
     }
 }
And then we define the Resource Class on the resource definition
/// <reference path="iphoneresourcedef.ts" />
module App.Resources {
    "use strict"; 
    export interface IPhoneResource
    extends ng.resource.IResourceClass<Resources.IPhoneResourceDef> {
    }
}

Now you can still reference to an IPhone object and have a concrete implementation of it and have a resource. As you can see, having type safety comes at a price. Remember that interfaces in JavaScript don’t exist and that this code won’t translate to any JavaScript code. All you are basically doing is providing scaffolding for type checking at compile time. Pure JavaScript fans will say they can write a lot more with a lot less code. I think they are right. I assume rock star programmers with an IQ of 200 can also go a lot faster if they don’t write unit tests for .NET code as well. The rest of us, the mere mortals, need all the help we can get.

Adding a resource builder

Now this may also seem like a lot of overkill, but believe me – when you start adding more and more resources to your app, you will se a lot of repetitive code in your AppBuilder. Me se not like that, to quote a beloved ;-) Star Wars character. So I came up with this Factory to build services for me:

module App.Factories {
    "use strict"; 
    export class ResourceBuilder{

        static $inject = ['$resource'];

        constructor(private $resource: ng.resource.IResourceService) {
        }

        public getPhoneResource(): Resources.IPhoneResource {
            return  this.$resource('/api/phones/:id', { id: '@id' }, { 
            });
        }
    }
} 

So then we mosey over to the AppBuilder.ts to add this factory and the resource we are building with it:

this.app.factory("ResourceBuilder", ['$resource',
    ($resource) => new Factories.ResourceBuilder($resource)]);

this.app.factory("PhoneResource",
    ["ResourceBuilder",
        (builder: App.Factories.ResourceBuilder) => builder.getPhoneResource()]);

This is added just below the declaration of the Angular modules, and just before the only controller we currently have.

Testing the setup

Basically we are done now – the only thing is to add code to show that all this actually works. So here we go again, as explained in the first post:

  • You add a new scope interface
  • You add a new controller
  • You add a view
  • You add the controller to the app and update the router.

Scope

For a quick demo, I am going to put some objects directly on the scope, which you normally would not do to prevent issues with sub scopes:

/// <reference path="../models/iphone.ts" />
module App.Scope {
    "use strict";

    export interface IPhoneScope {
        listOfPhones: Models.IPhone[];
        newPhone: Models.IPhone
    }
}

Add a new controller

/// <reference path="../models/iphone.ts" />
/// <reference path="../models/phone.ts" />
/// <reference path="../resources/iphoneresource.ts" />
/// <reference path="../scope/iphonescope.ts" />
/// <reference path="../models/phone.ts" />

module App.Controllers {
    "use strict";
    export class PhoneController {
        constructor(private $scope: Scope.IPhoneScope, 
                    private phoneResource: Resources.IPhoneResource) {
            $scope.listOfPhones = [];
            $scope.newPhone = new Models.Phone();
        }

        public doLoadPhones(): void {
            this.phoneResource.query({}, (d: Models.IPhone[]) => this.onLoaded(d));
        }

        private onLoaded(d: Models.IPhone[]): void {
            this.$scope.listOfPhones = d;
        }
         
        public doSavePhone(): void {
            this.phoneResource.save(this.$scope.newPhone,
                () => this.saveCallback(),
                () => { alert('failure'); });
        }

        private saveCallback() {
            alert('success');
            this.$scope.newPhone = new Models.Phone();
            this.doLoadPhones();
        }
    }
}

Not really rocket science here – a method to load phones from the server using the resource “query” method, and a method to save a phone using the resource “save” method. By inheriting ng.resource.IResourceClass we got all this methods for free, in stead of that we had to implement that all by ourselves using the $http stack.

Interlude - ways to mess up TypeScript callbacks
"I have not failed. I've just found 10,000 ways that won't work" - Thomas A. Edison

Sometimes you make typos, or honest mistakes. TypeScript, although being very powerful, has, like every other programming language, it’s own unique set of particular devious pitfalls that sometimes makes you wonder if someone made them on purpose. Observe way the callback is called:

public doSavePhone(): void {
    this.phoneResource.save(this.$scope.newPhone,
        () => this.saveCallback(),
        () => { alert('failure'); });
}

This works as intended. Now the fun thing is, if you just forget the parentheses at the end, e.g.

public doSavePhone(): void {
    this.phoneResource.save(this.$scope.newPhone,
        () => this.saveCallback,
        () => { alert('failure'); });
}

This will compile flawlessly. Only - the callback never gets called. Even more fun is this one:

public doSavePhone(): void {
    this.phoneResource.save(this.$scope.newPhone,
        this.saveCallback,
        () => { alert('failure'); });
}

This will compile, and saveCallBack will even be called. Only you will notice you have lost the "this" inside saveCallback. Ain’t life fun sometimes? Please take care when making callbacks. Don't fall into the same traps I did.

Add a new view

Then we add a new view phonesView.html in views:

<div>
  <div>
    Phones
    <div data-ng-repeat="phone in listOfPhones">
      <div>Name: {{phone.name}}; screen size: {{phone.screenSize}}"</div>
    </div>
  </div>

  <button data-ng-click="phoneController.doLoadPhones()">Load phones from server</button>
  <br /><br />
  Add a new phone<br />
  <label for="name" style="width:40px">Name</label>
  <input id="name" type="text" data-ng-model="newPhone.name" /><br />
  <label for="name" style="width:40px">Size</label>
  <input id="screensize" type="text" data-ng-model="newPhone.screenSize" /><br />
  <button data-ng-click="phoneController.doSavePhone()">Save</button>
</div>

Nothing special here, a div to show loaded fields and two text boxes to input a new one.

Update the AppBuilder with the new controller and route

First, we add the new controller. Nothing that we haven't seen before.
this.app.controller("phoneController", [
    "$scope", "PhoneResource", 
    ($scope: Scope.IPhoneScope, phoneResource: Resources.IPhoneResource)
        => new App.Controllers.PhoneController($scope, phoneResource )
]);
Then we add the new route to the controller, and make it the new default route. Also nothing new
this.app.config([
    "$routeProvider",
    ($routeProvider: ng.route.IRouteProvider) => { 
        $routeProvider
            .when("/person",
            {
                controller: "personController",
                controllerAs: "myController",
                templateUrl: "app/views/personView.html"
            })
            .when("/phones",
            {
                controller: "phoneController",
                controllerAs: "phoneController",
                templateUrl: "app/views/phonesView.html"
            })
            .otherwise({
                redirectTo: "/phones"
            });
    }
]);

Running the test

If you start the web application, you will initially see this:

image

Then, if you hit “Load phones from server”, it will show:

image

Then suppose we add the 530:

image

and hit save, we will see the “success” alert pop up, and finally,

image

Success at last.

Conclusion

This took me quite some time to figure out, and I am not one to sing my own praise but this may just be the only complete – and running – sample of using Angularjs resources with TypeScript. Most of what I wrote here is out there somewhere on the web, in bits and pieces, and sometimes partially wrong. Anyway. This works. Running sample solution, as always, can be downloaded here.

Now my only hope is that I won’t get sued over violating some copyright rules by defining a TypeScript interface whose name resembles a popular brand of phones made by a company whose name resembles a common fruit ;-)

30 July 2014

Sharing code between a Xamarin Forms/MVVMLight app and EF-code first backend using Shared Reference Project Manager

Disclaimer

I am in the very early early stages of toying with Xamarin and it may well be that whatever I am doing here, is not the smartest thing in the world. This is a much as a report of my learning (may ‘struggle’ is a better word) as how-to. But what I describe here works – more or less – although it was a mighty hassle to actually get it working.

The objective

While I was having my first trials with Xamarin stuff, I turned to Entity Framework Code First because, well, when setting up a backend I am lazy. Without much thinking I made the models, using data annotations, and soon found out I had painted myself into a corner with a model that (very simplified) looks like this

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace DemoShared.Models
{
   [Table("Pictures")]
    public class Photo
    {
      public long ID { get; set; }
      
     [Required]
      public string Name { get; set; }
    }
}

imageGuess what - data annotations don't work in PCL. Now what? Make a shadow class library for use on the client? That kind of went against my principles. So I decided to use the Shared Reference Project Manager.  This is a Visual Studio extension that can make basically any project shared, in stead of only between Windows Phone 8.1 and Windows 8.1 You can get it here.

Setting up the initial application

Using this tutorial by Laurent Bugnion I did set up my first Xamarin MVVM application. I created an app "DemoShared" and used the tutorial it up to the point where he starts making a new new xaml page (“Creating a new XAML page”).

Try to build the project. If the Windows Phone project fails with “The 'ProductID' attribute is invalid.. “ (etc), manually open it’s Properties/WMAppManifest.xml, for instance with NotePad, find “ProductID and “PubisherID” and place the generate GUIDs between accolades. This is a bug the Xamarin project template that I already reported.image

Basic setup of the backend

  • File/New Project/Web/ASP.Net Web application (it’s the only choice you have)
  • Choose a name (I chose DemoShared.Backend) and hit OK
  • Choose “Web Api” and UNSELECT “Host in the cloud”
  • Go to the NuGet Package manager and update all the packages, because a lot of them will be horribly outdated. Hit “accept” or “yes” on any questions
  • Delete the all folders except “App_Data”, “App_Start” and “Controllers” because we don’t need them
  • Delete BundleConfig.cs from App_Start, and remove the reference to it from Global.asax.cs as well
  • Add a (.NET) class library DemoShared.DataAccess
  • Install NuGet Package “EntityFrameWork” in DemoShared.Backend and DemoShared.DataAccess
  • Create a project DemoShared.Models of type Shared Project (Empty) of type Visual C#:

image

  • Right-click the DemoShared (Portable) project, select Add, then “Add Shared Project reference”, then select “DemoShared.Models
  • Repeat this procedure for DemoShared.DataAccess.
  • Also add a reference to System.ComponentModel.DataAnnotations to DemoShared.DataAccess.
  • Add DemoShared.DataAccess as a reference to DemoShared.Backend

Re-defining the models

The key point of this whole exercise is to re-use models. For one model class this is quite some overkill, but if you have a large collection of models, things becomes quite different. So anyway. I redefined the model class as follows:

#if NET45
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#endif

namespace DemoShared.Models
{
#if NET45
   [Table("Pictures")]
#endif

  public class Photo
  {
    public long ID { get; set; }

#if NET45     
     [Required]
#endif
    public string Name { get; set; }
  }
}

Now in order to make this compile work the way it is intended on server, you will need to add the conditional compilation symbol “NET45” to all configurations of DemoShared.DataAccess

image

And then it compiles both into PCL and into the DataAccess project – without the attributes in the first, but with the attributes the second. Remember, this is just a really nifty formalized way of ye olde way of file linking.

Kick starting the Entity Framework

Following this tutorial – more or less, I added the following class to the DataAccess project:

using System.Data.Entity;
using DemoShared.Models;

namespace DemoShared.DataAccess
{
  public class DemoContext : DbContext
  {
    public DemoContext()
      : base("DemoContext")
        {
        }

    public DbSet<Photo> Photos { get; set; }
  }
}

And then to the web.config I added this rather hopeless long connection string:

<connectionStrings>
  <add name="DemoContext" connectionString="Data Source=(localdb)\v11.0;AttachDbFilename=|DataDirectory|DemoDb.mdf;Initial Catalog=DemoDb;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
</connectionStrings>

Rebuild the project. Now go to the Backend Controller folder, right click Add/Controller, select “Web API 2 Controller with actions, using Entity Framework” and in the following dialog, select the Model and Data Context class as displayed to the right

imageimage

imageNow if you set “DemoShared.Backend” as start-up project, set it’s startup URL to “api/photos” and start the project, you will automatically get a database “DemoDb” in “App_Data”.Is EF code first cool or what? And my data annotations are used correctly – the Photo type is stored in the “Pictures” table, just as I wanted.

image

Now I manually entered some data in the tables to get something to show, but of course you can also write an initializer like the EF tutorial describes, or write a separate project that prefills the the database. This is what I usually do, and that’s why I have put the DemoContext in a separate assembly and not in the web project – to be able to reference it form another project.

And now finally, to the Xamarin app

Adding the view model

First of all – start the NuGet package manager and add Newtonsoft Json.NET to DemoShared (Portable).

Then, add a “ViewModels” folder to DemoShared (Portable) to hold this class:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Net;
using DemoShared.Models;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Newtonsoft.Json;

namespace DemoShared.ViewModels
{
  public class MainViewModel : ViewModelBase
  {
    public MainViewModel()
    {
      Photos = new ObservableCollection<Photo>();
    }

    public string DataUrl
    {
      get { return "http://169.254.80.80:28552/api/Photos"; }
    }

    public ObservableCollection<Photo> Photos { get; set; }

    private RelayCommand loadCommand;

    public RelayCommand LoadCommand
    {
      get
      {
        return loadCommand ?? (loadCommand = new RelayCommand(
            () =>
            {
              var httpReq = (HttpWebRequest)WebRequest.Create(new Uri(DataUrl));
              httpReq.BeginGetResponse((ar) =>
              {
                var request = (HttpWebRequest)ar.AsyncState;
                using (var response = (HttpWebResponse)request.EndGetResponse(ar))
                {
                  if (response.StatusCode == HttpStatusCode.OK)
                  {
                    using (var reader = new StreamReader(response.GetResponseStream()))
                    {
                      string content = reader.ReadToEnd();
                      if (!string.IsNullOrWhiteSpace(content))
                      {
                        var result = JsonConvert.DeserializeObject<List<Photo>>(content);
                        foreach (var g in result)
                        {
                          Photos.Add(g);
                        }
                      }
                    }
                  }
                }
              }, httpReq);
            }));
      }
    }

    private static MainViewModel instance;
    public static MainViewModel Instance
    {
      get
      {
        CreateNew();
        return instance;
      }
      set { instance = value; }
    }

    public static MainViewModel CreateNew()
    {
      if (instance == null)
      {
        instance = new MainViewModel();
      }
      return instance;
    }
  }
}

A rather standard MVVMLight viewmodel I might say, with the usual singleton pattern I use (I am not a big fan of "Locators"). When the command is fired, data is loaded from the WebApi url, deserialized to the same model code as was used to create it on the server, and loaded into the ObservableCollection. Nothing much special here.

There's one fishy detail - in stead of a computer name or “localhost”, there is this hard coded IP adress. We will get to that later.

Adding the Forms XAML page

Add a new Forms XAML page like this

image

Be aware that you have to enter the name manually, that’s a bug in the Xamarin tools, like Laurent Bugnion already described in his tutorial

Now, go to the DemoPage.Xaml.cs and set up the data context by adding one line of code to the constructor of the page:

public DemoPage()
{
  InitializeComponent();
  BindingContext = MainViewModel.Instance;
}

This will of course require a “using DemoShared.ViewModels;” at the top. Then we add our “XAML” to start page

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
		xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
		x:Class="DemoShared.DemoPage">
  <StackLayout Orientation="Vertical" Spacing="0">
    <Button Text="Click here" Command="{Binding LoadCommand}" 
            VerticalOptions="Start" HorizontalOptions="Center"  />
    <ListView ItemsSource="{Binding Photos}"
           RowHeight="50">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <StackLayout Padding="5, 5, 0, 5"
                           Orientation="Vertical"
                           Spacing="2">
                <Label Text="{Binding ID}" Font="Bold, Large" 
                       TextColor="Red"/>
              </StackLayout>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackLayout>
</ContentPage>

Now this looks kind of familiar, but also kind of - not really. Binding looks kind of you would expect, some controls have weird options, as some... well, have you ever seen a ViewCell before? Working with this stuff really makes you appreciate things like IntelliSense and Blend, for you have none of the above. Good old handcrafted XML. But - it does carry the magic of Xamarin Forms.

Finally, we make our start page the start page of the app. Go to App.cs in DemoShared (Portable) and change the GetMainPage method to:

public static Page GetMainPage()
{
  return new DemoPage();
}

imageimageThen I set a multiple startup project, setting both the Windows Phone project as well as the backend project as startup.

And sure enough, there’s the Windows Phone startup screen with one button. And if I click it…

 

I get an error.

And now for the fishy detail

So your backend is a website - running under IISExpress. By default, that’s not accessible by anything else but localhost, and not by IP adress. What you have to do is explained mostly here. First, find your applicationhost.config. It’s usually in

  • C:\Users\%USERNAME%\Documents\IISExpress\config or
  • D:\Users\%USERNAME%\Documents\IISExpress\config

In my case it’s the second one. Now before you start messing around in it, you might want to make a backup. Then open the file, and search for the text "*:28552”. This should yield you the following line:

<binding protocol="http" bindingInformation="*:28552:localhost" />

Make a copy of this line, directly below it. Replace localhost by the IP adress you found earlier using "ping -t –4 <hostname>". Net result, in my case:

<binding protocol="http" bindingInformation="*:28552:localhost" />
<binding protocol="http" bindingInformation="*:28552:169.254.80.80" />

Then – very important – close Visual Studio and restart as Administrator. For then and only then IISExpress will be allowed to bind to something else than localhost. That crucial bit of information is unfortunately hard to find.

And then, sure enough:

imageimage

It runs on Windows Phone and Android. And I am sure, on Apple stuff too but lacking Apple hardware and developer account I could not test it.

BTW – and alternative to messing around with IIS Express settings is of course host the website in IIS. But that requires apparently the database being hosted in SQL*Server Express, so it can’t be in App_Data like this. Or something like that. I found this made a quick test easier.

One more thing

If you want to test this from outside your computer, on a phone, you might want to open the port for TCP traffic:

image

Conclusion

Using Xamarin allowed us to shared code over multiple platform, but the Shared Reference Project Manager we could also share with the server. And the ease with which you can get a database powered backend up and running using EF code first was also quite impressive to me. Now tiny details, like security and upgrades, I leave as exercise to the reader.

Code can be found here.

Post scriptum

My fellow MVP Corrado Cavelli pointed out to me that the LoadCommand method in the MainViewModel can be made considerably less complex by using the Microsoft ASP.NET Web API 2.2 Client NuGet Package. He turns out to be quite right. When you add this to the portable class library you can rewrite the command to a relatively simple

public RelayCommand LoadCommand
{
  get
  {
    return loadCommand ?? (loadCommand = new RelayCommand(
        async () =>
              {
                var client = new HttpClient { 
                   BaseAddress = new Uri("http://169.254.80.80:28552") };
                var response = await client.GetAsync("api/Photos");
                var result = await response.Content.ReadAsAsync<List<Group>>();
                foreach (var g in result)
                {
                  Groups.Add(g);
                }
              }));
  }
}
This requires "using System.Net.Http;" and "using System.Threading.Tasks;" to be added to the file, but it's a lot less cluttered than my original - copied somewhere from the interwebz - code. Thanks Corrado!