Syncfusion Xamarin.Forms SfDataGrid – Binding to List<Dictionary<,>>

corresponding syncfusion forums post

Binding to Collection<Dictionary<,>> can be accomplished but doesn’t appear to be well documented… this WPF SfDataGrid doc gave the clue.

The basic trick is to set the SfDataGrid’s column.MappingName = “Fields[FieldName]”;
where Fields is a Dictionary property on your DictionaryWrapper class.

I couldn’t get List<Dictionary<string, object>> working directly without the wrapper class “hiding” the dictionary from what I think is an SfDataGrid bug. The app crash exception call stack ultimately winds up on an invalid Linq related get_Item() call.

Below is sample working code including “SimpleTable” wrapper for List and Newtonsoft type converter for deserializing Json “table” directly into this datastructure… this facilitates delivery of tabular resultsets from web api’s… see my SqlClientHelpers.ToJson method as one implementation that works succinctly within Azure Functions for example.

FYI, I believe there is also a bug with SfDataGrid column sorting logic when bound to this kind of Dictionary, a non-fatal exception fires. I worked around by implementing grid.SortColumnsChanging.

Sample Deserialize call:

var data = "[{\"Source\":\"Web\",\"Batch Id\":1}, {\"Source\":\"Manual\",\"Batch Id\":2}]";
var table = JsonConvert.DeserializeObject<SimpleTable>(data);

Binding sample with crucial MappingName syntax:

grid.ItemsSource = table;
grid.Columns.Add(new GridTextColumn()
{
  HeaderText = "Source",
  MappingName = "Vals[Source]" // **** HERE'S THE KICKER ****
});

SimpleTable.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataHelpers
{
  [JsonConverter(typeof(DictRow_DictDeserializer))]
  public class DictRow
  {
    public Dictionary<string, object> Vals { get; set; }
    public DictRow(Dictionary<string, object> dict) { Vals = dict; }
  }

  public class SimpleTable : List<DictRow>
  {
    public SimpleTable(IEnumerable<DictRow> list) : base(list) { }
  }

  public class DictRow_DictDeserializer : JsonConverter
  {
    public override bool CanRead => true;
    public override bool CanWrite => false;
    public override bool CanConvert(Type objectType) => objectType == typeof(Dictionary<string, object>);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
      return new DictRow(serializer.Deserialize<Dictionary<string, object>>(reader));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
      throw new NotSupportedException();
    }
  }
}

[SOLVED] Xamarin Forms iOS build error: An inconsistency between the local app and the remote build has been detected for _____. Please rebuild the application and try again.

image

there’s tons of hits on this but for me it seems to somehow be a “corrupt” solution file…

solution == new solution ; )

i spun up a new xam cross platform project solution and simply readded my existing PCL and iOS projects from the broken solution and it built and deployed to simulator just fine

keeping the old solution around for a rainy day diff

notables:

  • i am running Visual Studio 2017 RTM (15.0.0-RTW+26228.4) but i’m pretty sure i ran into this on VS2015 a while back as well.
  • tried upgrading all Windows and Mac bits to latest Xamarin Alpha
  • tried upgrading to the latest XCode (8.2.1)
  • walked throught the majority of this connection troubleshooting opus at the ready (gee Xam dudes, problems here much?)…
  • tried Clearing the Mac Build cache
  • enabled verbose logs (c:\> devenv /log)
  • there’s just nothing logged out to any of the Mac or Windows log folders for that error
  • i had another solution lying around that i created about a month ago when i ran into this error (same projects)… i just loaded it up and got the “inconsistency” error on the first run attempt, but then it actually went thru and launched the simulator upon second try – go figure

[SOLVED] Certain Font Awesome icons not showing in Xamarin iOS

Problem

None of the icons in the FA v4.7 release were showing up for me, while all the others were… so I had a basic working scenario but not entirely.

Background

  • I was doing a simple approach of showing the icons in a Label like so:
    <Label FontFamily="FontAwesome" Text="&#xf2b5;" />
  • I had my FontAwesome.ttf file under the iOS project’s Resources folder and via a font explorer tool I confirmed that the v4.7 icons were indeed present in that file
    • for the record, the new v4.7 icons look to begin at unicode hex xf2b5 (“handshake-o”)
    • I also had my own FontAwesome.ttf listed under my Info.plist > UIAppFonts along with another custom font I was using successfully
  • From previous approach, I also had the Iconize library loaded… with it’s “iconize-fontawesome.ttf” listed in Info.plist as well

[crayon title=”broken Info.plist (excerpt)” toolbar=”always”]
UIAppFonts

iconize-fontawesome.ttf
iconize-material.ttf
RichardsonBrandAccelerator.ttf
FontAwesome.ttf

[/crayon]

Solution

The clue that tipped me off was that i noticed Iconize was built with an older version of FontAwesome… so as a guess, I re-ordered my FontAwesome.ttf entry ABOVE the iconize-fontawesome.ttf like below… and wouldn’t you know it, that actually did the trick! : )

[crayon title=”WORKING Info.plist (excerpt)” toolbar=”always”]
UIAppFonts

RichardsonBrandAccelerator.ttf
FontAwesome.ttf
iconize-fontawesome.ttf
iconize-material.ttf

[/crayon]

Xamarin iOS Provisioning Gotchas

I managed to create scenario where debugging from Visual Studio 2017 to iOS Simulator was giving me absolute fits because the error messages are so unhelpful… as usual, it was my own fault of course, but gosh it’s scary how easily one can fall in that deep dark pit where hopes and dreams go to die ; )

Example Error Messages

  • Application X need to be rebuilt due to an inconsistency between the connected Mac and the local app
  • Visual Studio cannot start the application automatically because it was signed with a Distribution provisioning profile. Please start it by tapping the application icon on the device

TL;DR

In my case it was because the “Bundle ID” aka “App ID” set in my info.plist was incompatible with the provisioning profiles actually available on my Mac build host and selected in the iOS project settings.

More background

  1. My Provisioning Certificates had expired (as we know, issued from http://Developer.Apple.com) … that did throw me off for a bit but eventually I got the clue and went through the Apple Developer account renewal process…
  2. Funny thing, I’d been waiting for our Apple Enterprise Developer aka In House distribution account to finalize… I noticed it had finally opened up (there’s a big yellow sign indicating 2wk delay between approval and the corresponding “In House” radio button becoming available on the provisioning profile page) and decided to just run with that vs my personal Developer keys…
  3. This meant I was creating all the necessary provisioning bits from scratch…
  4. First up, creating my App ID aka Bundle Id record (cue foreboding thunderclap)… ‘course when you’re establishing a new name, it’s always fun to apply your more current understanding of just what that name should be… here’s where I messed up, this App ID gets embedded in the provisioning profile which must then be the same as what’s in your iOS project’s info.plist > CFBundleIdentifier entry !!
  5. So while I did realize I needed to go select those new Identity/Provisioning profile entries in the iOS project settings > iOS Bundle Signing page, there’s nothing obvious in the error messaging to smack us in the head about App Id conflict.

Saving Grace

reading this post… suggested compiling under Xamarin Studio on the Mac for more error visibility… that’s a good basic technique reminder… I also use Xcode for this at times… at this point we’ve got Visual Studio for Mac so i fired that up and it did indeed provide significantly more helpful messaging, which got me back on track – Good to know !

Developer vs Distribution Profile – what’s the difference?

Somehow I’d never really run smack into this but one pertinent difference during development is that choosing a Distribution Profile will require you to manually launch your app on the iOS Simulator vs Visual Studio being able to launch it for you… so choose a Developer profile until you’re really in the mode to push builds out to real end user devices.

image

Troubleshooting Prism Xamarin Forms

for the record i’m currently running with the Unity DI framework

totally silent app crash on NavigateAsync

this is super frustrating when you don’t get any exception stack at all to go on…
i can’t tell you how many times i’ve brainfarted a simple typo bug which blows up the xaml parse … so check that well before you get too cranky… e.g. i always forget the “{Binding }” around my commands!?!?
but if you can easily, temporarily set your initial page navigation (typically in your App.xaml.cs::App.OnInitialized) to go directly to your offending page
and then make sure to put a .Wait() on the end of the call… doing these two things allows the otherwise silent exceptions to show up and hopefully that’s just the clue you need

ViewModelLocationProvider naming bug

i stumbled into naming one of my pages “PdfView” and it went haywire not binding to my “PdfViewViewModel” but instead probably the first viewmodel instantiated

Exposing Azure Function web API to native & web clients through Azure AD authentication

Problem

Azure AD writeups are prevalent but I was really struggling to find examples of calling the same Azure Function API, secured by Azure AD Authentication, by both Native as well as Web clients (since we can only select one app type in the Azure AD App registration, not both).

TL;DR

The kicker solution for me was having both a web and native App registration (i.e. two Client Id’s) and providing the WEB App registration’s Application Id as the “RESOURCE” parameter to the AuthenticationContext.AcquireTokenAsync() call in the Native app (see code sample below).

So the web registration is tied directly to the Azure Function… and then we’re piggybacking the web registration by requesting the web as the resource parameter in the native client call … i haven’t seen this documented yet so i can’t say whether this is an officially preferred solution.

Basic Steps

This is a good getting started guide guide, in parity with current landscape.

  1. get your Azure Function working as a web api… probably doesn’t matter whether web or native comes first but it seems like the web is more “trusted” from an OAuth standpoint and more clearly documented… OAuth refers to native clients as “public” and requiring a couple more OAuth contortions than web clients.
  2. create a Web type entry for your Function under New Portal > Azure Active Directory > App registrations… all the defaults are good, except you’ll need to create the Reply URLs that are valid for you… reply url is a parameter to your ADAL.js client call… in the end this entry provides the crucial Application Id aka Client Id
  3. now configure this web registration for AD Auth via New Portal > App Services > {your Function app} > Function app settings > Configure authentication > Authentication Providers > Azure AD > Express >
    1. Azure AD App = the Web App registration name you gave above
  4. Now create another Azure AD > App registration as Native type and (HERE’S THE KICKER) > Settings > Required Permissions > Add > Select an API > TYPE IN YOUR web App registration name in the search box and it’ll show up to be selected
  5. finally, use the Application Id guid from your web app as the RESOURCE parameter to the AcquireTokenAsync() call in your native app

Working ADAL.js web client code sample

function adalResultHandler(err, token) {
  if (err) {
    self.userName(null);
    lobibox.notify("error", { size: "mini", title: "Azure AD Auth", msg: err });
    return false;
  } else {
    self.userName(adal.getCachedUser().profile.name);
    //lobibox.notify("info", { size: "mini", msg: "login successful\nuser: " + user.profile.name + "\ntoken: " + token });
    return true;
  }
}

var adal = new AuthenticationContext({
  instance: "https://login.microsoftonline.com/",
  tenant: "{your domain}.onmicrosoft.com",
  clientId: "{your web guid}", // your Azure AD > App registrationS > {your web api} > APPLICATION ID
  //NUGGET: these "reply URLs" are set under Azure Portal > AD > App registrations > {your App Service} > Settings > Reply URLs
  //NOT under {your App Service} > Settings > (Manage) Auth > AD > Redirect URLs !!!
  redirectUri: window.location.href, //REPLACE WITH YOUR REDIRECT URL
  popUp: true
});

adal.callback = function (err, token) { if (adalResultHandler(err, token)) doSomething(); }

adal.login();

Working Xamarin Native iOS app client code sample

private const string Instance = "https://login.microsoftonline.com";
private const string Tenant = "{your domain}.onmicrosoft.com"; //common //COMMON OR YOUR TENANT ID // "hfcazure.com", //"4be68759-0968-4760-b716-f82711a28fcb", //http://stackoverflow.com/questions/26384034/how-to-get-the-azure-account-tenant-id
private const string ClientId = "{your native guid}"; //from your Azure AD > App registrations > {your ***NATIVE*** api} > APPLICATION ID
private const string RedirectUri = "https://{your azure function api name}.azurewebsites.net";
private const string ResourceId = "{your web guid}"; //take this from your Azure AD > App registrations > {your ***WEB*** api} > APPLICATION ID // **isn't that interesting, we're requesting another API as the "resource" of this api**

var Azure_OAuth2_Authority_Url = $"{Instance}/{Tenant}/oauth2/authorize");
var authContext = new AuthenticationContext(Azure_OAuth2_Authority_Url);

var authResult = await authContext.AcquireTokenAsync(ResourceId, ClientId, new Uri(RedirectUri), await _platformParameters.GetAsync()); //_platformParameters is something i whipped up special
CurrentUser = new HfcUserAuth
{
  FirstName = authResult.UserInfo?.GivenName,
  LastName = authResult.UserInfo?.FamilyName,
  AccessToken = authResult.AccessToken,
  IdToken = authResult.IdToken
};

Typical error responses

Various attempts at sussing out a valid resource value for the AcquireTokenAsync() in my Xamarin Forms native iOS app would yield the following error:
AADSTS65005: The client application has requested access to resource <xyz>. This request has failed because the client has not specified this resource in its requiredResourceAccess list

i was also getting these where {app} was the resource i was passing when i had the ClientId parameter wrong
AADSTS50001: The application named {app} was not found in the tenant named {tentant}.

Helpful references

What is my Tenant Id or “Authority” URL ???

Wanted to mention this in closing since “Tentant” is currently so ambiguously referred to in the documentation i ran into…
New Portal > Azure Active Directory > App registrations > Endpoints is where you pull the “Authority” Url from the “OAUTH 2.0 AUTHORIZATION ENDPOINT” slot – the main argument for new AuthenticationContext()

for example:
https://login.windows.net/9198d419-6ce5-4229-a457-8c38421f7466/oauth2/authorize
this “9198…” guid is your Tenant Id (don’t worry this one is made up)

our tenant appears to be simply our azure ad domain name, at least in typical configurations… so this works here as well:
https://login.windows.net/XYZ.onmicrosoft.com/oauth2/authorize

image

Solving Visual Studio 2017 -> Xamarin Mac Agent connectivity issues

this seems to be a recurring theme for me so i expect to be throwing more bones on this pile as the sands of time leave behind our lives sublime

Xamarin Forums Post

i had VS2017 doing iOS builds just yesterday but for some reason was getting persist Mac Agent “can’t connect” errors today… and zilch in the xam logs to go on, yikes… thankfully struck me to look at Mac “Console” system.log and noticed

Nov 21 20:28:50 McBeejBerg com.apple.xpc.launchd[1] (com.openssh.sshd.D3C4B936-497A-46B7-8592-E6AC9E714711[21887]): Service exited with abnormal code: 255

… firing every time just opening the VS Mac Agent connection dialog… googled that error and tried this

sudo vi /private/etc/sshd_config # Beej: i'm on Mac Sierra, maybe why i didn't have existing sshd_config file... the sands are always shifting beneath us... but did have /etc/ssh_config (note, no "d") with this pass auth setting commented out
# PasswordAuthentication yes
sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd

thankfully it’s actually connecting after that (phew) … for the record, same errors are still firing in mac system.log, so maybe just recycling sshd service is the huckleberry here

Lighter Spin on ADAL in Xamarin Forms

tl;dr

new-up the elusive “PlatformParameters” in your AppDeligate.cs::FinishedLoading / MainActivity.cs::OnCreate
 

ts;wm (too short; want more ; )

thankfully we have solid writeups on ADAL with XF… this post is just me trying to boil it down to essence and PCL as much as possible…
(BTW: ADAL = Active Directory Auth Lib… i needed it for PowerBI embedding)

  1. http://www.appzinside.com/2016/02/22/implement-adal-for-cross-platform-xamarin-applications/
  2. https://blog.xamarin.com/authenticate-mobile-apps-using-microsoft-authentication-library/

the first post keeps the platform specific surface area pretty minimal but also winds up wrappering the stock ADAL classes quite a bit…
the second post seems pretty minimal and leverages CustomRenderers for the right timing to grab this context… seems like a good general trick to tuck away…
 

the approach i came to is grabbing this context right up front in app initialization and then providing it through dependency injection later…
both pieces of that are basically one liners which feels nice
also it’s now conveniently available to other services should needs arise…
and theoretically we’ve kept things clean for TDD but honestly i don’t readily see how to test this flow since it requires interactive auth… i’ll have to read up on how people generally recommend mocking this kind of thing
 

iOS AppDeligate.cs::FinishedLoading()

  public partial class AppDelegate : Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
  {
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
      Xamarin.Forms.Forms.Init();

      var prismApp = new App(new iOSInitializer());
      LoadApplication(prismApp);

      var finishedLaunchingResult = base.FinishedLaunching(app, options);
      //KeyWindow won't be populated until after FinishedLaunching
      prismApp.Container.RegisterInstance(typeof(IPlatformParameters), new PlatformParameters(UIApplication.SharedApplication.KeyWindow.RootViewController)); // ** here's the beef **

      return finishedLaunchingResult;
      }
  }

Android MainActivity.cs::OnCreate

  public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
  {
    protected override void OnCreate(Bundle bundle)
    {

      base.OnCreate(bundle);

      Xamarin.Forms.Forms.Init(this, bundle);
      var prismApp = new App(new AndroidInitializer());
      LoadApplication(prismApp);

      prismApp.Container.RegisterInstance(typeof(IPlatformParameters), new PlatformParameters(this)); // ** here's the beef **
    }
  }

then later in calling code just reference via DI

    public PowerBIService(IPlatformParameters platformParameters)
    {
      _platformParameters = platformParameters;
    }

Toggle XAML <> Code-Behind in Visual Studio 2015, ReSharper, Xamarin Forms

Quickly bouncing between .XAML and corresponding .CS file just seems like an obvious need… i feel like we used to have this in WPF but it’s been a few years for me.

Short Story:

  • this approach simply maps preferred hotkey to ReSharper’s “Go To Related Files” command… sorry if that’s not an expense you care to bear but it’s a great tool for numerous reasons if you can spring for it
  • Visual Studio > Tools menu > Options > Environment > Keyboard
  • “Show commands containing” edit box enter: relatedfiles
  • select “ReSharper.ReSharper_GotoRelatedFiles”
  • “Use new shortcut in” drop down select: Text Editor
  • “Press shortcut keys” edit box press: F7
  • lastly click “Assign” button and “OK” and you’re done

image

 

ViewModel class in .xaml.cs file

if you happen to be using the Prism framework’s automatic ViewModel binding, consider throwing your ViewModel (VM) classes into the {View}.xaml.cs file…
that way the F7 key will now bounce back and forth between the XAML and the VM bound to it, lovely!

i know this is kinda controversial at first blush but think about it for a sec before jumping on condemnation…
at this point VM is the predominant paradigm for the “code behind” a view… the actual view class is likely to be empty.
admittedly, VM’s are not necessarily 1-to-1 with a View… they can be swapped out, many views to one model and driven by TDD… yet that is all still possible, we are merely talking about which .cs file the VM class definition is contained

image