<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-03-06T09:19:07+00:00</updated><id>/feed.xml</id><title type="html">Timothé Larivière</title><subtitle>My journey as a .NET developer </subtitle><entry><title type="html">Mastering Jetpack Compose, SwiftUI, and Flutter: Expanding My Mobile Expertise</title><link href="/2025/03/05/mastering-jetpack-compose-swiftui-and-flutter-expanding-my-mobile-expertise/" rel="alternate" type="text/html" title="Mastering Jetpack Compose, SwiftUI, and Flutter: Expanding My Mobile Expertise" /><published>2025-03-05T00:00:00+00:00</published><updated>2025-03-05T00:00:00+00:00</updated><id>/2025/03/05/mastering-jetpack-compose-swiftui-and-flutter-expanding-my-mobile-expertise</id><content type="html" xml:base="/2025/03/05/mastering-jetpack-compose-swiftui-and-flutter-expanding-my-mobile-expertise/"><![CDATA[<h2 id="a-decade-of-mobile-development-and-beyond">A Decade of Mobile Development and Beyond</h2>
<p>Over the past eleven years, I’ve worked on everything from high-performance microservices handling billions of hotel bookings to a government-backed mobile app that helps citizens record biodiversity in Australia. But no matter what I’ve worked on, mobile development has always been what I love most.</p>

<p>For almost nine years, I’ve been dedicated to creating mobile apps that users interact with daily, ensuring a smooth experience, optimal performance, and scalable architecture.</p>

<p>Since 2020, my journey has taken an exciting turn into freelancing, where I help businesses build, maintain, and scale their mobile applications. A large part of this expertise has come from co-creating and maintaining <a href="https://fabulous.dev">Fabulous</a>, a declarative mobile framework for .NET, inspired by architectures like SwiftUI and Elm. My contributions to this field have also been recognized through five consecutive Microsoft MVP awards.</p>

<p>With this foundation, it’s time to push my expertise further—by mastering Jetpack Compose, SwiftUI, and Flutter.</p>

<h2 id="why-learn-new-mobile-frameworks">Why Learn New Mobile Frameworks?</h2>
<p>Mobile development is always evolving, and keeping up means embracing modern UI frameworks. While React Native is a major player, I prefer strongly typed languages, as I believe a proper type system prevents over 90% of common bugs. That’s one of many ways JavaScript falls short, which is why I’m drawn to Jetpack Compose (Kotlin), SwiftUI (Swift), and Flutter (Dart).</p>

<p>These frameworks have become the go-to choices for Android, iOS, and cross-platform development, and knowing all three lets me offer businesses the right tool for the job instead of a one-size-fits-all approach.</p>

<p>But it’s not just about picking up new technologies—it’s about seeing how different frameworks solve the same problems in their own way. Learning multiple approaches helps refine best practices, improve architecture, and ultimately build better apps.</p>

<h2 id="what-truly-separates-a-great-mobile-developer">What Truly Separates a Great Mobile Developer?</h2>
<p>A common misconception in hiring and evaluating engineers is focusing solely on years of experience with a specific technology. While experience is valuable, true expertise comes from understanding the core principles of software engineering—which translate across languages and frameworks.</p>

<p>Through my work over the years, I have already developed expertise in:</p>

<ul>
  <li><strong>Business Goals</strong> – Understanding user and stakeholder needs and translating them into features</li>
  <li><strong>User Experience</strong> – Designing smooth, performant, and accessible apps for a delightful experience</li>
  <li><strong>Software Architecture</strong> – Building scalable, maintainable, and modular systems</li>
  <li><strong>State Management</strong> – Choosing the right architecture for the app’s needs (MVU, MVVM, Redux, etc.)</li>
  <li><strong>Performance Optimization</strong> – Ensuring responsiveness and efficient memory use</li>
  <li><strong>CI/CD Pipelines</strong> – Automating builds, testing, and deployment for mobile apps</li>
  <li><strong>App Distribution</strong> – Navigating Apple &amp; Google Play requirements for seamless deployment</li>
</ul>

<p>These skills aren’t framework-dependent—they are fundamental to great mobile development.</p>

<p>Mastering new mobile UI frameworks isn’t about starting from scratch—it’s about adapting existing expertise to different ecosystems.</p>

<h2 id="my-advantage-building-a-framework-from-the-inside-out">My Advantage: Building a Framework from the Inside Out</h2>
<p>Most developers learn new frameworks by watching tutorials, reading documentation, and experimenting. My approach is different—I have already built a mobile UI framework.</p>

<p>For over seven years, my work on Fabulous has given me inside-out knowledge of what makes declarative UI frameworks powerful and scalable. This experience gives me a unique perspective when learning new frameworks, as I can analyze not just how they work, but why they were designed the way they are.</p>

<p>Through this journey, I aim to apply my deep understanding of declarative UI to Jetpack Compose, SwiftUI, and Flutter while refining my approach to mobile development across ecosystems.</p>

<h2 id="understanding-the-similarities-between-frameworks">Understanding the Similarities Between Frameworks</h2>
<p>One of the reasons I feel confident jumping into these new frameworks is that I already understand the core principles behind them. Declarative UI frameworks share fundamental concepts, including unidirectional data flow, state management, and component-based design.</p>

<p>To illustrate, here’s a simple counter app implemented in SwiftUI, Jetpack Compose, and Fabulous:</p>

<h3 id="swiftui">SwiftUI</h3>
<div class="language-swift highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">struct</span> <span class="kt">CounterView</span><span class="p">:</span> <span class="kt">View</span> <span class="p">{</span>
    <span class="kd">@State</span> <span class="kd">private</span> <span class="k">var</span> <span class="nv">count</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">var</span> <span class="nv">body</span><span class="p">:</span> <span class="kd">some</span> <span class="kt">View</span> <span class="p">{</span>
        <span class="kt">VStack</span> <span class="p">{</span>
            <span class="kt">Text</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">count</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
            <span class="kt">Button</span><span class="p">(</span><span class="s">"Increment"</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="jetpack-compose">Jetpack Compose</h3>
<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Composable</span>
<span class="k">fun</span> <span class="nf">CounterView</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="py">count</span> <span class="k">by</span> <span class="nf">remember</span> <span class="p">{</span> <span class="nf">mutableStateOf</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">}</span>

    <span class="nc">Column</span> <span class="p">{</span>
        <span class="nc">Text</span><span class="p">(</span><span class="s">"$count"</span><span class="p">)</span>
        <span class="nc">Button</span><span class="p">(</span><span class="n">onClick</span> <span class="p">=</span> <span class="p">{</span> <span class="n">count</span><span class="p">++</span> <span class="p">})</span> <span class="p">{</span>
            <span class="nc">Text</span><span class="p">(</span><span class="s">"Increment"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="fabulous">Fabulous</h3>
<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="nc">CounterView</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="nc">Component</span><span class="bp">()</span> <span class="p">{</span>
        <span class="k">let</span><span class="o">!</span> <span class="n">count</span> <span class="p">=</span> <span class="nn">Context</span><span class="p">.</span><span class="nc">State</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

        <span class="nc">VStack</span><span class="p">(</span><span class="n">spacing</span> <span class="p">=</span> <span class="mi">20</span><span class="o">.)</span> <span class="p">{</span>
            <span class="nc">Text</span><span class="o">($</span><span class="s2">"{count.Current}"</span><span class="p">)</span>
            <span class="nc">Button</span><span class="p">(</span><span class="s2">"Increment"</span><span class="p">,</span> <span class="k">fun</span> <span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">count</span><span class="p">.</span><span class="nc">Set</span><span class="p">(</span><span class="n">count</span><span class="p">.</span><span class="nc">Current</span> <span class="o">+</span> <span class="mi">1</span><span class="o">))</span>
        <span class="p">}</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>These examples demonstrate how similar modern UI frameworks have become. While the syntax differs, the underlying concepts—such as state-driven rendering and UI composition—are nearly identical.</p>

<h2 id="introducing-snapdex-a-production-quality-playground-for-my-learning">Introducing Snapdex: A Production-Quality Playground for My Learning</h2>
<p>As I embark on mastering these frameworks, I wanted a real-world project to apply my knowledge. That’s why I started working on Snapdex.</p>

<h3 id="what-is-snapdex">What is Snapdex?</h3>
<p>Inspired by the Pokédex from Pokémon, Snapdex is an app that lets users track Pokémon they encounter in the real world. Whether it’s a plush toy, a poster, a trading card, or even a sound clip from a video game or TV, users can take pictures or record audio, and the app will use AI-powered recognition to identify the Pokémon and unlock its corresponding entry in the Pokédex.</p>

<p>This project is an opportunity to demonstrate expertise across the full spectrum of mobile development, ensuring a seamless and high-quality user experience:</p>
<ul>
  <li><strong>User Experience &amp; Interface</strong> – Designing clean, intuitive, and visually appealing UI with smooth animations.</li>
  <li><strong>Robust Architecture</strong> – Implementing best practices in MVI, MVVM, and Clean Architecture for maintainability.</li>
  <li><strong>Data Management &amp; Offline Support</strong> – Handling API calls, local database persistence, and seamless offline syncing.</li>
  <li><strong>Security &amp; Authentication</strong> – Protecting user data with encrypted storage, secure tokens, and access controls.</li>
  <li><strong>Cloud &amp; AI Integration</strong> – Leveraging Firebase/AWS for backend services and AI-powered Pokémon recognition.</li>
  <li><strong>Platform-Specific Features</strong> – Accessing camera, microphone, dark mode, system notifications, and deep linking.</li>
  <li><strong>Performance &amp; Stability</strong> – Optimizing image caching, monitoring analytics, and ensuring crash resilience.</li>
  <li><strong>Automation &amp; Deployment</strong> – Streamlining development with CI/CD, Gradle, Swift Package Manager, and automated testing.</li>
  <li><strong>Localization &amp; Accessibility</strong> – Adapting the app for multiple languages and inclusive design.</li>
</ul>

<p>Each of these aspects will be carefully designed and implemented, ensuring that Snapdex is not just a functional app, but a showcase of best practices in modern mobile development.</p>

<p>Everything will be open-source on <a href="https://github.com/TimLariviere/Snapdex">GitHub</a>, allowing you to see my work firsthand and evaluate my expertise in real-world scenarios.</p>

<h3 id="why-snapdex">Why Snapdex?</h3>
<ul>
  <li>It involves rich UI interactions, perfect for testing new frameworks</li>
  <li>It requires high-performance rendering, a challenge across mobile platforms</li>
  <li>It’s a fun and engaging project, keeping me motivated as I learn</li>
</ul>

<p>By developing Snapdex in Jetpack Compose, SwiftUI, and Flutter, I can directly compare how each framework handles UI composition, animations, performance optimizations, and scalability.</p>

<h2 id="looking-ahead">Looking Ahead</h2>
<p>Mastering these frameworks is more than just a technical challenge—it’s about broadening my expertise, increasing my flexibility, and preparing for the future of mobile development.</p>

<p>I believe that the best mobile developers aren’t defined by a single framework, but by their understanding of core engineering principles. Jetpack Compose, SwiftUI, and Flutter represent the future of mobile development, and I’m excited to push my skills further by diving deep into each of them.</p>

<p>This is the next chapter of my journey—and I’m eager to share what I learn along the way.</p>

<h3 id="final-thoughts">Final Thoughts</h3>
<p>If you’re also navigating the shift to modern declarative UI frameworks, I’d love to hear your thoughts! Have you transitioned to Jetpack Compose, SwiftUI, or Flutter? What challenges did you face, and how did your prior experience shape your learning process? Let’s connect and learn together.</p>

<h3 id="follow-my-progress">Follow My Progress:</h3>

<ul>
  <li>Find me at <strong><a href="https://timothelariviere.com">https://timothelariviere.com</a></strong></li>
  <li>Follow <strong><a href="https://github.com/TimLariviere/Snapdex">Snapdex on GitHub</a></strong></li>
  <li>Learn more about <strong><a href="https://fabulous.dev">Fabulous</a></strong></li>
  <li>Connect with me on <strong><a href="https://linkedin.com/in/timlariviere">LinkedIn</a></strong></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[A Decade of Mobile Development and Beyond Over the past eleven years, I’ve worked on everything from high-performance microservices handling billions of hotel bookings to a government-backed mobile app that helps citizens record biodiversity in Australia. But no matter what I’ve worked on, mobile development has always been what I love most.]]></summary></entry><entry><title type="html">Introducing Fabulous 2.0</title><link href="/2022/06/01/introducing-fabulous-20/" rel="alternate" type="text/html" title="Introducing Fabulous 2.0" /><published>2022-06-01T00:00:00+00:00</published><updated>2022-06-01T00:00:00+00:00</updated><id>/2022/06/01/introducing-fabulous-20</id><content type="html" xml:base="/2022/06/01/introducing-fabulous-20/"><![CDATA[<p>After almost a year of hard work, I am very excited to announce <a href="https://github.com/fsprojects/Fabulous">Fabulous 2.0</a>!<br />
This new release is a complete rewrite of Fabulous, focusing on performance and developer experience.</p>

<p>Version 2.0 is the first of several major releases.<br />
It comes with a brand new DSL inspired by SwiftUI and improved performance to ensure the best possible development experience.</p>

<p>In later releases, we will introduce support for MAUI and support for components to help you scale your apps with ease.<br />
If you’re interested, you can read more about it here: <a href="https://docs.fabulous.dev/v2/architecture/goals-of-v2">Reasonable goals of v2</a></p>

<p>I want to thank all Fabulous contributors for their contributions and support over the years.<br />
Special thanks to <a href="https://twitter.com/twopSK">Simon Korzunov (@twopSK)</a> for helping design the new architecture and for his awesome work on performance improvements, and <a href="https://twitter.com/efgpdev">Edgar Gonzalez (@efgpdev)</a> for his first contributions in Open Source by patiently mapping all Xamarin.Forms controls to Fabulous 2.0 and providing a lot of feedback.</p>

<h2 id="whats-new-in-version-20">What’s new in version 2.0</h2>

<h3 id="new-view-dsl">New View DSL</h3>

<p>We’re introducing a new DSL for Fabulous, inspired by SwiftUI.<br />
This DSL is more concise, easier to extend and features proper type-safety to ensure your code is readable and always working as intended.</p>

<p>It makes use of 2 new concepts: Widgets and Modifiers.</p>

<p>Widgets are the building blocks of your UI. You compose them together to define what your app looks like.<br />
Some of those widgets will require essential properties to be passed as parameters: for example <code class="language-plaintext highlighter-rouge">Label</code> requires a <code class="language-plaintext highlighter-rouge">text</code> parameter, <code class="language-plaintext highlighter-rouge">Button</code> requires a <code class="language-plaintext highlighter-rouge">text</code> and <code class="language-plaintext highlighter-rouge">onClicked</code> parameters, etc.</p>

<p>In v1.0, properties were available as optional parameters and some as extension methods.<br />
Now in v2.0, properties are now all set through modifiers.</p>

<p>Those modifiers are accessible via the dot notation.</p>

<pre><code class="language-fs">Label("Hello, World")
    .font(namedSize = NamedSize.Large, fontFamily = "Arial")
    .textColor(light = FabColor.Red, dark = FabColor.Blue)
    .horizontalTextAlignment(TextAlignment.Center)
    .padding(10.)
</code></pre>

<p>Thanks to the strongly-typed nature of Widget, the compiler will now prevent you from combining incompatible widgets.</p>

<p><img src="/assets/2022-06-01-introducing-fabulous-20/widget-incompatible-types.png" alt="Error message when combining incompatible widgets" /></p>

<p>And your IDE will only show you the modifiers available for the current widget.</p>

<p><img src="/assets/2022-06-01-introducing-fabulous-20/ide-experience-v2.png" alt="IDE experience in v2.0" /></p>

<p>For comparison, here is the same UI in both v1.0 and v2.0:</p>

<pre><code class="language-fs">/// Fabulous 1.0
let view model dispatch =
    View.ContentPage(
        title = "Home",
        content =
            View.StackLayout(
                orientation = StackOrientation.Vertical,
                spacing = 8.0,
                children = [
                    View.Label(
                        text = "Welcome to Fabulous 1.0!",
                        fontSize = FontSize.FromNamedSize(NamedSize.Large)
                    )

                    View.Label(
                        text = $"Click count = {model.Count}"
                    )

                    View.Button(
                        text = "Click me!",
                        command = (fun () -&gt; dispatch ButtonClicked),
                        foregroundColor = Color.FromHex("#FF0000")
                    )
                ]
            )
    )
    
// Fabulous 2.0
let view model =
    ContentPage("Home",
        VStack(spacing = 8.0) {
            Label("Welcome to Fabulous 2.0!")
                .font(namedSize = NamedSize.Large)

            Label($"Click count = {model.Count}")
            
            Button("Click me!", ButtonClicked)
                .foregroundColor(FabColor.fromHex "#FF0000")
        }
    )
</code></pre>

<p>You may have noticed <code class="language-plaintext highlighter-rouge">dispatch</code> is missing in Fabulous 2.0. We take care of dispatching messages for you now, so you can focus on the UI itself.</p>

<h3 id="focus-on-performance">Focus on performance</h3>

<p>The second major improvement is reduced allocations on hot paths. This will make your apps faster and more responsive.</p>

<p>Almost all the internal infrastructure of Fabulous now works with structs instead of classes.<br />
This drastically reduces GC pressure on your apps by keeping as much as possible on the stack.</p>

<p>We’ve also optimized for CPU cache misses to achieve even better performances.</p>

<p>And finally, we optimized for trimming in Release builds to produce the smallest binaries possible.</p>

<p><em>Comparison of dll sizes for FabulousContacts between Fabulous 1.0 and 2.0 (iOS release build with linker enabled)</em></p>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>1.0</th>
      <th>2.0</th>
      <th>Difference</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Fabulous.dll</td>
      <td>57 KB</td>
      <td>209 KB</td>
      <td>+152 KB</td>
    </tr>
    <tr>
      <td>Fabulous.XamarinForms.dll*</td>
      <td>8.43 MB</td>
      <td>1.08 MB</td>
      <td>-7.35 MB</td>
    </tr>
    <tr>
      <td>Fabulous.XamarinForms.Maps.dll</td>
      <td>219 KB</td>
      <td>N/A**</td>
      <td>-219 KB</td>
    </tr>
    <tr>
      <td>FabulousContacts.dll</td>
      <td>171 KB</td>
      <td>158 KB</td>
      <td>-13 KB</td>
    </tr>
    <tr>
      <td>Total</td>
      <td>8.87 MB</td>
      <td>1.44 MB</td>
      <td><strong>-7.43 MB (-83.8%)</strong></td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>Estimated App Install Size***</td>
      <td>48.5 MB</td>
      <td>42.0 MB</td>
      <td><strong>-6.5 MB (-13.4%)</strong></td>
    </tr>
  </tbody>
</table>

<p>More than 80% reduction in dll size overall for Fabulous 2.0, leading to 13% size reduction for the FabulousContacts app itself!<br />
This is a huge improvement over 1.0.</p>

<p><sub>* Please note that for some dlls, the F# optimization and signature data can make for a big chunk of the dll size (2/3 in case of F.XF.dll, about ~0.7 MB).<br />
Those data are not used at runtime but the Xamarin linker doesn’t remove them.<br />
After we start support for MAUI, the dll sizes will be much smaller thanks to the .NET 6.0 linker removing those unused data.</sub></p>

<p><sub>** Fabulous.XamarinForms.Maps is not available yet for Fabulous 2.0.<br />
Instead the Map widget has been directly integrated into FabulousContacts.</sub></p>

<p><sub>*** Decompressed IPA files</sub></p>

<h3 id="better-3rd-party-support-and-extensibility">Better 3rd party support and extensibility</h3>

<p>With the new Widgets and Modifiers, extending an existing widget is as easy as declaring an extension method!<br />
Also makes it very easy to add 3rd party support.</p>

<p>Here is an example of adding support for the <code class="language-plaintext highlighter-rouge">Xamarin.Forms.Map</code> control:</p>

<pre><code class="language-fs">// Declare a marker interface (used for strong-typing the widget)
type IMap = inherit Fabulous.XamarinForms.IView

module Map =
    // Tell Fabulous to instantiate Xamarin.Forms.Map when using Map widget
    let WidgetKey = Widgets.register&lt;Xamarin.Forms.Map&gt;()

    // Define which properties will be available
    let RequestedRegion = Attributes.defineSimpleScalarWithEquality&lt;MapSpan&gt; (...) // code omitted for brevity
    let HasZoomEnabled = Attributes.defineBindableBool Xamarin.Forms.Map.HasZoomEnabledProperty
    let HasScrollEnabled = Attributes.defineBindableBool Xamarin.Forms.Map.HasScrollEnabledProperty

[&lt;AutoOpen&gt;]
module MapBuilders =
    type Fabulous.XamarinForms.View with
        // Expose Map widget with a specific constructor (requestedRegion will be mandatory)
        static member inline Map&lt;'msg&gt;(requestedRegion) =
            WidgetBuilder&lt;'msg, IMap&gt;(
                Map.WidgetKey,
                Map.RequestedRegion.WithValue(requestedRegion)
            )

[&lt;Extension&gt;]
type MapModifiers =
    // Define the withZoom modifier
    [&lt;Extension&gt;]
    static member inline withZoom(this: WidgetBuilder&lt;'msg, #IMap&gt;, ?enabled: bool) =
        let value = match enabled with None -&gt; true | Some v -&gt; v
        this.AddScalar(Map.HasZoomEnabled.WithValue(value))

    // Define the withScroll modifier
    [&lt;Extension&gt;]
    static member inline withScroll(this: WidgetBuilder&lt;'msg, #IMap&gt;, ?enabled: bool) =
        let value = match enabled with None -&gt; true | Some v -&gt; v
        this.AddScalar(Map.HasScrollEnabled.WithValue(value))

// Usage
Map(MapSpan.FromCenterAndRadius(...))
    .withZoom()
    .withScroll(false)
</code></pre>

<h2 id="support-for-other-frameworks">Support for other frameworks</h2>

<p>One key feature of Fabulous is the possibility to be integrated with frameworks, other than Xamarin.Forms.</p>

<p>We made it even easier in version 2.0 by providing the whole reconciliation infrastructure directly as part of the Fabulous library.<br />
All you need to do to integrate Fabulous with your framework is to implement the widgets and modifiers you need.</p>

<p>Fabulous will take care of the rest.</p>

<h2 id="new-fabulous-website">New Fabulous website</h2>

<p>Along with this new release, we also launched a new website dedicated to Fabulous.</p>

<p><a href="https://fabulous.dev">https://fabulous.dev</a></p>

<p>It’s a great place to learn more about Fabulous, and to see how it’s used in the wild.<br />
Documentation is available at <a href="https://docs.fabulous.dev">https://docs.fabulous.dev</a></p>

<p>Right now, the website is in a very early stage, but we’re working hard to make it as useful as possible.<br />
We are currently focusing on adding more documentation for 2.0.</p>

<p>We are looking for contributors to help us improve the website itself.<br />
If you’re interested in contributing to the website, please contact us on the Fabulous <a href="https://discord.gg/bpTJMbSSYK">Discord channel</a>.</p>

<h2 id="get-started-today">Get started today</h2>

<p>You can start right now by installing the <a href="https://www.nuget.org/packages/Fabulous.XamarinForms.Templates">templates</a> available on NuGet!</p>

<p>Follow the Getting Started guide to learn start to use Fabulous 2.0: <a href="https://docs.fabulous.dev/v2/getting-started">https://docs.fabulous.dev/v2/getting-started</a></p>

<p>If you have any questions, feel free to ask them on the <a href="https://discord.gg/bpTJMbSSYK">Discord channel</a> or raise issues on GitHub: <a href="https://github.com/fsprojects/Fabulous">https://github.com/fsprojects/Fabulous</a><br />
We are also available on Twitter <a href="https://twitter.com/FabulousAppDev">@FabulousAppDev</a>.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[After almost a year of hard work, I am very excited to announce Fabulous 2.0! This new release is a complete rewrite of Fabulous, focusing on performance and developer experience.]]></summary></entry><entry><title type="html">How to become a Fabulous developer</title><link href="/2019/12/21/how-to-become-a-fabulous-developer/" rel="alternate" type="text/html" title="How to become a Fabulous developer" /><published>2019-12-21T00:00:00+00:00</published><updated>2019-12-21T00:00:00+00:00</updated><id>/2019/12/21/how-to-become-a-fabulous-developer</id><content type="html" xml:base="/2019/12/21/how-to-become-a-fabulous-developer/"><![CDATA[<p>It’s the 21st day of the <a href="https://sergeytihon.com/2019/11/05/f-advent-calendar-in-english-2019/">F# Advent Calendar 2019</a>, only 4 days left before Christmas!</p>

<p>If this year, like all the previous ones, you wrote Santa asking him to bring a new framework finally letting you write apps you’ll love, with a clean, easy-to-use, reliable, maintainable and testable architecture, your present has come early!</p>

<p>Today, we will see together what Fabulous is, what it offers, and how it helps you build apps that you will finally be proud of.</p>

<h1 id="f-and-the-mvu-architecture">F# and the MVU architecture</h1>

<p>Recently, frameworks like Elm, React-Redux and Flutter became really popular thanks in part to their alternative approach to app development, showing that mainstream MVC / MVVM architectures were not the only way to go.</p>

<p>Elm introduced its own architecture: MVU, standing for Model View Update, which inspired Redux.</p>

<p>The concept is to have a central state (the model) that can only be updated through messages sent by the UI when the user interacts with it, or by a “subscription” sending messages at any point in time (e.g. a push notification, an asynchronous task that completes, etc.).<br />
When the state is updated, the view is reevaluated to define how it should look for this particular state.</p>

<p><img src="https://elmprogramming.com/images/chapter-5/5.2-model-view-update-part-1/model-view-update.svg" alt="Model View Update" />
<em>Credits: Beginning Elm (<a href="https://elmprogramming.com">https://elmprogramming.com</a>)</em></p>

<p>This architecture has several advantages over traditional ones:</p>
<ul>
  <li>
    <p><em>Centralized state and updates</em><br />
The immutability of the state is one of the greatest asset of MVU.<br />
It ensures that developers can only update the state through messages, declared in an enum-like type, thus centralizing all possible changes.<br />
No more implicit changes, sometimes hidden deep in the source code, that can be understood only if you know perfectly how the application works.</p>
  </li>
  <li>
    <p><em>No concurrency issues</em><br />
By updating the state only through messages, it allows the framework to apply concurrent messages one after the other.</p>
  </li>
  <li>
    <p><em>Explicit views at each update</em><br />
In a typical app framework, you would define your UI once and react to the user input by updating parts of it little by little. So to understand what made the UI look that way, you need to mentally reenact what the user did.<br />
In MVU, you’re no longer responsible for that. Instead, each time the state is updated, you’re asked to provide the complete view for this particular state (usually through a virtual representation) without having to think about what was the previous UI. The framework takes the responsability to update the UI.</p>
  </li>
  <li>
    <p><em>Reproducible views</em><br />
The fact your view is reevaluated each time the state is updated means that you can write side effect-free functions (aka pure functions) to generate the view according to a given state. This means that if you provide the same state, you will get the exact same view. Very convenient to test!</p>
  </li>
</ul>

<p>At any time, you know the complete state of your application and can trace what sequence of messages brought it to that state. (time-travel debugging FTW!)</p>

<p>For more information on MVU, please read <a href="https://guide.elm-lang.org/architecture/">the Elm’s website</a>.</p>

<p>This architecture is a perfect match for functional programming.<br />
Pure functions, immutability, exhaustive pattern matching and so on. All are natural attributes of functional languages, like F#!</p>

<p>Hence, the architecture of Elm was ported to the F# programming language: <a href="https://elmish.github.io/elmish/">Elmish</a> was born.</p>

<h1 id="what-about-fabulous">What about Fabulous?</h1>

<p>Fabulous is heavily inspired by Elmish. They, in fact, share a common approach to MVU.</p>

<p>Fabulous is an open-source, community driven set of .NET Standard 2.0 libraries to write apps in F# using an MVU architecture <a href="https://www.nuget.org/packages?q=Fabulous">available as NuGet packages</a>.<br />
The source code can be found on <a href="https://github.com/fsprojects/Fabulous">GitHub</a>.</p>

<p><img src="/assets/2019-12-21-how-to-become-a-fabulous-developer/fabulous-ecosystem.png" alt="Fabulous and its ecosystem" /></p>

<p>It started as <code class="language-plaintext highlighter-rouge">Elmish.XamarinForms</code>, providing only something called “static views” based on Xamarin.Forms. Later on, a “dynamic views” approach (still for Xamarin.Forms) has been introduced and it was renamed <code class="language-plaintext highlighter-rouge">Fabulous</code> for the occasion. Finally, it evolved in a set of platform-agnostic libraries, allowing you to use your favorite framework by adding support for it with a small adapter library.</p>

<p>The Xamarin.Forms part has been extracted into its own adapter library. But it remains the only officially supported framework as of today.</p>

<p>While Elmish decided to let the users “bring their own views” by not forcing a way to declare views, Fabulous provides several ways to define them: static, dynamic and adaptive views.</p>

<p>They all use the same building blocks:</p>
<ul>
  <li>A model (usually named <code class="language-plaintext highlighter-rouge">Model</code>)</li>
  <li>A set of messages (usually named <code class="language-plaintext highlighter-rouge">Msg</code>)</li>
  <li>An <code class="language-plaintext highlighter-rouge">init</code> function giving the default model at the start of the application</li>
  <li>An <code class="language-plaintext highlighter-rouge">update</code> function applying the corresponding changes to the model for a given message, returning a new model</li>
  <li>A <code class="language-plaintext highlighter-rouge">view</code> function that will apply the new model to the UI</li>
</ul>

<p>Once we have all those building blocks, we can assemble them in a <code class="language-plaintext highlighter-rouge">Program</code> that we will use to start the MVU application loop.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">open</span> <span class="nc">Fabulous</span>

<span class="k">type</span> <span class="nc">Model</span> <span class="p">=</span>
    <span class="p">{</span> <span class="nc">Count</span><span class="p">:</span> <span class="kt">int</span> <span class="p">}</span>

<span class="k">type</span> <span class="nc">Msg</span> <span class="p">=</span>
    <span class="p">|</span> <span class="nc">Increment</span>
    <span class="p">|</span> <span class="nc">Decrement</span>

<span class="k">let</span> <span class="n">init</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">0</span> <span class="p">}</span>

<span class="k">let</span> <span class="n">update</span> <span class="n">msg</span> <span class="n">model</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">msg</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Increment</span> <span class="p">-&gt;</span> <span class="p">{</span> <span class="n">model</span> <span class="k">with</span> <span class="nc">Count</span> <span class="p">=</span> <span class="n">model</span><span class="p">.</span><span class="nc">Count</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}</span>
    <span class="p">|</span> <span class="nc">Decrement</span> <span class="p">-&gt;</span> <span class="p">{</span> <span class="n">model</span> <span class="k">with</span> <span class="nc">Count</span> <span class="p">=</span> <span class="n">model</span><span class="p">.</span><span class="nc">Count</span> <span class="p">-</span> <span class="mi">1</span> <span class="p">}</span>

<span class="k">let</span> <span class="n">view</span> <span class="o">...</span> <span class="p">=</span>
    <span class="c1">// We will see how we can define our UI later in this post</span>
    <span class="o">...</span>

<span class="k">let</span> <span class="n">program</span> <span class="p">=</span> <span class="nn">Program</span><span class="p">.</span><span class="n">mkSimple</span> <span class="n">init</span> <span class="n">update</span> <span class="n">view</span>
</code></pre></div></div>

<p>One of the advantages of this architecture is that it’s completely composable.<br />
As the application grows, you can create sub-components with their own <code class="language-plaintext highlighter-rouge">Model</code>/<code class="language-plaintext highlighter-rouge">Msg</code>/<code class="language-plaintext highlighter-rouge">init</code>/<code class="language-plaintext highlighter-rouge">update</code>/<code class="language-plaintext highlighter-rouge">view</code> that you can call inside their parent component.</p>

<h1 id="the-view-function-your-choice">The view function, your choice</h1>

<p>All the examples will use Xamarin.Forms. Like said before, Fabulous was initially all about Xamarin.Forms so it remains the most fully supported framework.</p>

<p>To see the difference between each way to write a view, we will take the same application, a simple counter app.</p>

<video height="420" controls="" loop="">
  <source src="/assets/2019-12-21-how-to-become-a-fabulous-developer/counterapp.mov" type="video/mp4" />
</video>

<p>Fabulous has been tested on the following platforms supported by Xamarin.Forms:</p>
<ul>
  <li>Android</li>
  <li>iOS</li>
  <li>UWP</li>
  <li>WPF</li>
  <li>macOS</li>
  <li>GTK</li>
</ul>

<h4 id="static-views">Static views</h4>

<p>Fabulous.StaticView is a good way to gently move from an existing application to an F# MVU one, or make apps with heavy and complex UIs while benefiting from the advantages of Fabulous.</p>

<p>The concept is very similar to <a href="https://github.com/elmish/Elmish.WPF">Elmish.WPF</a>. You define the whole state of the application using MVU but the UI keeps getting declared in its native language (XAML for Xamarin.Forms, Storyboard for iOS, etc.).</p>

<p>In the view function, you expose a set of values and event handlers to the UI.<br />
With Xamarin.Forms, this is done through bindings.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Binding.oneWay exposes a value from the current model</span>
<span class="c1">// Binding.msg creates a command that will send a message when executed</span>
<span class="k">let</span> <span class="n">view</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="p">[</span> <span class="s2">"CounterValue"</span> <span class="p">|&gt;</span> <span class="nn">Binding</span><span class="p">.</span><span class="n">oneWay</span> <span class="p">(</span><span class="k">fun</span> <span class="n">m</span> <span class="p">-&gt;</span> <span class="n">m</span><span class="p">.</span><span class="nc">Count</span><span class="p">)</span>
      <span class="s2">"IncrementCommand"</span> <span class="p">|&gt;</span> <span class="nn">Binding</span><span class="p">.</span><span class="n">msg</span> <span class="nc">Increment</span>
      <span class="s2">"DecrementCommand"</span> <span class="p">|&gt;</span> <span class="nn">Binding</span><span class="p">.</span><span class="n">msg</span> <span class="nc">Decrement</span> <span class="p">]</span>
</code></pre></div></div>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;ContentPage&gt;</span>
    <span class="nt">&lt;StackLayout&gt;</span>
        <span class="nt">&lt;Label</span> <span class="na">Text=</span><span class="s">"{Binding Path=[Count]}"</span> <span class="na">HorizontalOptions=</span><span class="s">"Center"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;Button</span> <span class="na">Text=</span><span class="s">"Increment"</span> <span class="na">Command=</span><span class="s">"{Binding Path=[IncrementCommand]}"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;Button</span> <span class="na">Text=</span><span class="s">"Decrement"</span> <span class="na">Command=</span><span class="s">"{Binding Path=[DecrementCommand]}"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/StackLayout&gt;</span>
<span class="nt">&lt;/ContentPage&gt;</span>
</code></pre></div></div>

<p>Now that our <code class="language-plaintext highlighter-rouge">view</code> function is declared, we can start our application with our previously declared <code class="language-plaintext highlighter-rouge">program</code>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">FabulousApp</span><span class="bp">()</span> <span class="k">as</span> <span class="n">this</span> <span class="p">=</span> 
    <span class="k">inherit</span> <span class="nn">Xamarin</span><span class="p">.</span><span class="nn">Forms</span><span class="p">.</span><span class="nc">Application</span> <span class="bp">()</span>

    <span class="k">let</span> <span class="n">runner</span> <span class="p">=</span>
        <span class="n">program</span>
<span class="p">#</span><span class="k">if</span> <span class="nc">DEBUG</span>
        <span class="p">|&gt;</span> <span class="nn">Program</span><span class="p">.</span><span class="n">withConsoleTrace</span>
<span class="p">#</span><span class="n">endif</span>
        <span class="p">|&gt;</span> <span class="nn">Program</span><span class="p">.</span><span class="n">runWithStaticView</span>
    
    <span class="k">do</span> <span class="n">this</span><span class="p">.</span><span class="nc">MainPage</span> <span class="p">&lt;-</span> <span class="n">runner</span><span class="p">.</span><span class="nc">InitialMainPage</span>
</code></pre></div></div>

<p>Notice the <code class="language-plaintext highlighter-rouge">Program.withConsoleTrace</code>?<br />
This allows us to check what’s going on in our application. It’s a logging mechanism that plugs directly in the MVU loop of Fabulous.<br />
Each time a model is initialized or a message is sent, we will see what the model was and how it was changed as well as if there was an error updating the UI.</p>

<p>See <a href="https://github.com/fsprojects/Fabulous/tree/master/Fabulous.StaticView">Fabulous.StaticView on the Fabulous repository</a> for more information</p>

<h4 id="dynamic-views">Dynamic views</h4>

<p>Fabulous “Dynamic Views” (shortened to Fabulous) is the most popular option of the 3.<br />
Instead of writing views using your framework’s native view language, you write it directly in F# via a special <code class="language-plaintext highlighter-rouge">View</code> module that wraps all the supported controls.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">view</span> <span class="n">model</span> <span class="n">dispatch</span> <span class="p">=</span>
    <span class="nn">View</span><span class="p">.</span><span class="nc">ContentPage</span><span class="p">(</span>
        <span class="nn">View</span><span class="p">.</span><span class="nc">StackLayout</span><span class="o">([</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="n">model</span><span class="p">.</span><span class="nn">Count</span><span class="p">.</span><span class="nc">ToString</span><span class="bp">()</span><span class="p">,</span> <span class="n">horizontalOptions</span> <span class="p">=</span> <span class="nn">LayoutOptions</span><span class="p">.</span><span class="nc">Center</span><span class="p">)</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="s2">"Increment"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Increment</span><span class="p">)</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="s2">"Decrement"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Decrement</span><span class="p">)</span>
        <span class="o">])</span>
    <span class="p">)</span>

<span class="k">type</span> <span class="nc">FabulousApp</span> <span class="bp">()</span> <span class="k">as</span> <span class="n">app</span> <span class="p">=</span> 
    <span class="k">inherit</span> <span class="nc">Application</span> <span class="bp">()</span>

    <span class="k">let</span> <span class="n">runner</span> <span class="p">=</span>
        <span class="n">program</span>
<span class="p">#</span><span class="k">if</span> <span class="nc">DEBUG</span>
        <span class="p">|&gt;</span> <span class="nn">Program</span><span class="p">.</span><span class="n">withConsoleTrace</span>
<span class="p">#</span><span class="n">endif</span>
        <span class="p">|&gt;</span> <span class="nn">XamarinFormsProgram</span><span class="p">.</span><span class="n">run</span> <span class="n">app</span>
</code></pre></div></div>

<p>This has a lot of advantages over the previous approach:</p>
<ul>
  <li>
    <p><em>One language to rule them all</em><br />
Why having to learn and use 2 (or more) different languages, with uneven tooling support, to write an app? A lot of people tend to prefer to use a single language, even if it means no designer view or harder to write constructs like bindings.<br />
With “Dynamic Views”, you write everything in F#, including views. No more runtime errors because you provided the wrong value to a property (or mistyped that binding name once again…).<br />
The F# compiler will be there to help you.</p>
  </li>
  <li>
    <p><em>Virtual views and incremental updates</em><br />
For performance reasons, the views you write don’t directly instantiate the actual controls. Instead, Fabulous will apply a diff’ing algorithm to check what changed between the new virtual view and the previous one, and apply only the required changes.<br />
This is called incremental updates.</p>
  </li>
  <li>
    <p><em>Adapted to functional use</em><br />
Since Fabulous provides its own wrappers over the controls, it’s able to make them more functional-friendly.</p>
  </li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">/// Bindings</span>
<span class="p">&lt;</span><span class="nc">Label</span> <span class="nc">Text</span><span class="p">=</span><span class="s2">"{Binding Value}"</span> <span class="o">/&gt;</span>
<span class="n">vs</span><span class="p">.</span>
<span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="n">model</span><span class="p">.</span><span class="nc">Value</span><span class="p">)</span>

<span class="c1">/// Columns and rows</span>
<span class="p">&lt;</span><span class="nc">Grid</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nn">Grid</span><span class="p">.</span><span class="nc">ColumnDefinitions</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nc">ColumnDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"Auto"</span> <span class="o">/&gt;</span>
        <span class="p">&lt;</span><span class="nc">ColumnDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"*"</span> <span class="o">/&gt;</span>
        <span class="p">&lt;</span><span class="nc">ColumnDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"2.5*"</span> <span class="o">/&gt;</span>
    <span class="o">&lt;/</span><span class="nn">Grid</span><span class="p">.</span><span class="nc">ColumnDefinitions</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nn">Grid</span><span class="p">.</span><span class="nc">RowDefinitions</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nc">RowDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"Auto"</span> <span class="o">/&gt;</span>
        <span class="p">&lt;</span><span class="nc">RowDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"*"</span> <span class="o">/&gt;</span>
        <span class="p">&lt;</span><span class="nc">RowDefinition</span> <span class="nc">Width</span><span class="p">=</span><span class="s2">"2.5*whoops mistyped here"</span> <span class="o">/&gt;</span>
    <span class="o">&lt;/</span><span class="nn">Grid</span><span class="p">.</span><span class="nc">RowDefinitions</span><span class="p">&gt;</span>
<span class="o">&lt;/</span><span class="nc">Grid</span><span class="p">&gt;</span>

<span class="n">vs</span><span class="p">.</span>

<span class="nn">View</span><span class="p">.</span><span class="nc">Grid</span><span class="p">(</span>
    <span class="n">coldefs</span> <span class="p">=</span> <span class="p">[</span> <span class="nc">Auto</span><span class="p">;</span> <span class="nc">Star</span><span class="p">;</span> <span class="nc">Stars</span> <span class="mi">2</span><span class="p">.</span><span class="mi">5</span> <span class="o">],</span>
    <span class="n">rowdefs</span> <span class="p">=</span> <span class="p">[</span> <span class="nc">Auto</span><span class="p">;</span> <span class="nc">Star</span><span class="p">;</span> <span class="nc">Stars</span> <span class="mi">2</span><span class="p">.</span><span class="mi">5</span> <span class="p">]</span>
<span class="p">)</span>

<span class="c1">/// DataTemplate / ItemsSource / Converter</span>
<span class="p">&lt;</span><span class="nc">ListView</span> <span class="nc">ItemsSource</span><span class="p">=</span><span class="s2">"{Binding Items}"</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nn">ListView</span><span class="p">.</span><span class="nc">ItemTemplate</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nc">DataTemplate</span><span class="p">&gt;</span>
            <span class="p">&lt;</span><span class="nc">ViewCell</span><span class="p">&gt;</span>
                <span class="p">&lt;</span><span class="nc">Label</span> <span class="nc">Text</span><span class="p">=</span><span class="s2">"{Binding Name}"</span>
                       <span class="nc">TextColor</span><span class="p">=</span><span class="s2">"{Binding IsMinor, Converter={StaticResource BoolToTextColorConverter}}"</span> <span class="o">/&gt;</span>
            <span class="o">&lt;/</span><span class="nc">ViewCell</span><span class="p">&gt;</span>
        <span class="o">&lt;/</span><span class="nc">DataTemplate</span><span class="p">&gt;</span>
    <span class="o">&lt;/</span><span class="nn">ListView</span><span class="p">.</span><span class="nc">ItemTemplate</span><span class="p">&gt;</span>
<span class="o">&lt;/</span><span class="nc">ListView</span><span class="p">&gt;</span>

<span class="k">public</span> <span class="k">class</span> <span class="nc">BoolToTextColorConverter</span> <span class="p">:</span> <span class="nc">IValueConverter</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>

<span class="p">&lt;</span><span class="nc">Application</span> <span class="n">xmlns</span><span class="p">:</span><span class="n">local</span><span class="p">=</span><span class="s2">"..."</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nn">Application</span><span class="p">.</span><span class="nc">Resources</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="n">local</span><span class="p">:</span><span class="nc">BoolToTextColorConverter</span> <span class="n">x</span><span class="p">:</span><span class="nc">Key</span><span class="p">=</span><span class="s2">"BoolToTextColorConverter"</span> <span class="o">/&gt;</span>
    <span class="o">&lt;/</span><span class="nn">Application</span><span class="p">.</span><span class="nc">Resources</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nc">Application</span><span class="p">&gt;</span>

<span class="n">vs</span><span class="p">.</span>

<span class="nn">View</span><span class="p">.</span><span class="nc">ListView</span><span class="o">([</span>
    <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">model</span><span class="p">.</span><span class="nc">Items</span> <span class="p">-&gt;</span>
        <span class="k">yield</span> <span class="nn">View</span><span class="p">.</span><span class="nc">ViewCell</span><span class="p">(</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span>
                <span class="n">text</span> <span class="p">=</span> <span class="n">item</span><span class="p">.</span><span class="nc">Name</span><span class="p">,</span>
                <span class="n">textColor</span> <span class="p">=</span> <span class="k">if</span> <span class="n">item</span><span class="p">.</span><span class="nc">IsMinor</span> <span class="k">then</span> <span class="nn">Color</span><span class="p">.</span><span class="nc">Red</span> <span class="k">else</span> <span class="nn">Color</span><span class="p">.</span><span class="nc">Blue</span>
            <span class="p">)</span>
        <span class="p">)</span>
<span class="o">])</span>
</code></pre></div></div>

<p>Those are only a few examples. And F# 4.7 will remove the need for <code class="language-plaintext highlighter-rouge">yield</code> and prefixing with <code class="language-plaintext highlighter-rouge">View.</code>.</p>

<p>As you may have seen in the last example, since this is F# code, you can easily write conditional views.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">match</span> <span class="n">model</span><span class="p">.</span><span class="nc">UserData</span> <span class="k">with</span>
<span class="p">|</span> <span class="nc">None</span> <span class="p">-&gt;</span>
    <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="s2">"Log in"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="k">fun</span> <span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">StartLogin</span><span class="p">)</span>
<span class="p">|</span> <span class="nc">Some</span> <span class="n">user</span> <span class="p">-&gt;</span>
    <span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span>
        <span class="n">text</span> <span class="p">=</span> <span class="n">user</span><span class="p">.</span><span class="nc">Name</span><span class="p">,</span>
        <span class="n">textColor</span> <span class="p">=</span> <span class="k">if</span> <span class="n">user</span><span class="p">.</span><span class="nc">IsPremium</span> <span class="k">then</span> <span class="nn">Color</span><span class="p">.</span><span class="nc">Gold</span> <span class="k">else</span> <span class="nn">Color</span><span class="p">.</span><span class="nc">Black</span>
    <span class="p">)</span>
</code></pre></div></div>

<p>Fabulous lets you write any kind of apps easily. Here’s a few open-source ones using dynamic views:</p>

<p><img height="420" src="/assets/2019-12-21-how-to-become-a-fabulous-developer/fsharp-weekly.png" />
<img height="420" src="https://raw.githubusercontent.com/TimLariviere/FabulousContacts/master/docs/attachments/detail.png" />
<img height="420" src="https://raw.githubusercontent.com/TimLariviere/FabulousPlanets/master/docs/attachments/fabulousplanets-wip.gif" /></p>

<p><em>(From left to right: <a href="https://github.com/Zaid-Ajaj/fsharp-weekly">FSharp Weekly</a>, <a href="https://github.com/TimLariviere/FabulousContacts">FabulousContacts</a> and <a href="https://github.com/TimLariviere/FabulousPlanets">FabulousPlanets</a>)</em></p>

<p>Templates are available to help you start a new solution.<br />
More information in the <a href="https://fsprojects.github.io/Fabulous/Fabulous.XamarinForms/index.html#getting=started">Getting Started</a> guide and on the <a href="https://github.com/fsprojects/Fabulous">Fabulous repository</a>.</p>

<h4 id="adaptive-views">Adaptive views</h4>

<p><a href="https://github.com/dsyme/fabulous-adaptive">AdaptiveFabulous</a> can be seen as a mix of the two previous approaches.</p>

<p>Like dynamic views, you declare the UI through a virtual representation that gets called on each update. But for increased performance (in intensive use cases, like real-time data), it also supports immediate bindings that will update the UI directly instead of waiting for a complete reevaluation.</p>

<p>This is achieved thanks to <a href="https://github.com/fsprojects/FSharp.Data.Adaptive">FSharp.Data.Adaptive</a>.</p>

<p>Currently, it is completely experimental and is developed by Don Syme.</p>

<p>A conversion is currently needed between the “classic” model and the adaptive one. But this will be eventually automated with <a href="https://github.com/krauthaufen/Adaptify">Adaptify</a>.</p>
<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">/// An adaptive version of the model. </span>
<span class="k">type</span> <span class="nc">AdaptiveModel</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span><span class="p">:</span> <span class="n">cval</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="p">}</span>

<span class="c1">/// Initialize an adaptive version of the model.</span>
<span class="k">let</span> <span class="n">ainit</span> <span class="p">(</span><span class="n">model</span><span class="p">:</span> <span class="nc">Model</span><span class="p">)</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Text</span> <span class="p">=</span> <span class="n">cval</span> <span class="n">model</span><span class="p">.</span><span class="nc">Count</span> <span class="p">}</span>

<span class="c1">/// Update an adaptive version of the model. </span>
<span class="k">let</span> <span class="n">adelta</span> <span class="p">(</span><span class="n">model</span><span class="p">:</span> <span class="nc">Model</span><span class="p">)</span> <span class="p">(</span><span class="n">amodel</span><span class="p">:</span> <span class="nc">AdaptiveModel</span><span class="p">)</span> <span class="p">=</span>
    <span class="n">transact</span> <span class="p">(</span><span class="k">fun</span> <span class="bp">()</span> <span class="p">-&gt;</span> 
        <span class="k">if</span> <span class="n">model</span><span class="p">.</span><span class="nc">Count</span> <span class="p">&lt;&gt;</span> <span class="n">amodel</span><span class="p">.</span><span class="nn">Count</span><span class="p">.</span><span class="nc">Value</span> <span class="k">then</span> 
            <span class="n">amodel</span><span class="p">.</span><span class="nn">Count</span><span class="p">.</span><span class="nc">Value</span> <span class="p">&lt;-</span> <span class="n">model</span><span class="p">.</span><span class="nc">Count</span>
    <span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">c</code> and <code class="language-plaintext highlighter-rouge">cs</code> mean that the values are constants and won’t change dynamically so there’s no need to listen to their changes. <code class="language-plaintext highlighter-rouge">amodel.Count</code> on the other hand will change.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">view</span> <span class="n">amodel</span> <span class="n">dispatch</span> <span class="p">=</span>
    <span class="nn">View</span><span class="p">.</span><span class="nc">ContentPage</span><span class="p">(</span><span class="n">c</span>
        <span class="nn">View</span><span class="p">.</span><span class="nc">StackLayout</span><span class="p">(</span><span class="n">cs</span> <span class="p">[</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="n">amodel</span><span class="p">.</span><span class="nc">Count</span><span class="p">,</span> <span class="n">horizontalOptions</span> <span class="p">=</span> <span class="n">c</span> <span class="nn">LayoutOptions</span><span class="p">.</span><span class="nc">Center</span><span class="p">)</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="n">c</span> <span class="s2">"Increment"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="n">c</span> <span class="p">(</span><span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Increment</span><span class="o">))</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">text</span> <span class="p">=</span> <span class="n">c</span> <span class="s2">"Decrement"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="n">c</span> <span class="p">(</span><span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Decrement</span><span class="o">))</span>
        <span class="o">])</span>
    <span class="p">)</span>
</code></pre></div></div>

<p>See <a href="https://github.com/dsyme/fabulous-adaptive">the AdaptiveFabulous repository</a> for more information</p>

<h1 id="testing-the-application">Testing the application</h1>

<p>Our application is composed of 3 major parts: init, update and view.<br />
They’re all functions, even more, they are pure, making them perfect candidates for unit testing!</p>

<p>Before we start testing them, we need to set identifiers to let our tests know which control is which.
This is done through <code class="language-plaintext highlighter-rouge">automationId</code>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">view</span> <span class="n">model</span> <span class="n">dispatch</span> <span class="p">=</span>
    <span class="nn">View</span><span class="p">.</span><span class="nc">ContentPage</span><span class="p">(</span>
        <span class="nn">View</span><span class="p">.</span><span class="nc">StackLayout</span><span class="o">([</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Label</span><span class="p">(</span><span class="n">automationId</span> <span class="p">=</span> <span class="s2">"CountLabel"</span><span class="p">,</span> <span class="n">text</span> <span class="p">=</span> <span class="n">model</span><span class="p">.</span><span class="nn">Count</span><span class="p">.</span><span class="nc">ToString</span><span class="bp">()</span><span class="p">)</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">automationId</span> <span class="p">=</span> <span class="s2">"IncrementButton"</span><span class="p">,</span> <span class="n">text</span> <span class="p">=</span> <span class="s2">"Increment"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Increment</span><span class="p">)</span>
            <span class="nn">View</span><span class="p">.</span><span class="nc">Button</span><span class="p">(</span><span class="n">automationId</span> <span class="p">=</span> <span class="s2">"DecrementButton"</span><span class="p">,</span> <span class="n">text</span> <span class="p">=</span> <span class="s2">"Decrement"</span><span class="p">,</span> <span class="n">command</span> <span class="p">=</span> <span class="k">fun</span><span class="bp">()</span> <span class="p">-&gt;</span> <span class="n">dispatch</span> <span class="nc">Decrement</span><span class="p">)</span>
        <span class="o">])</span>
    <span class="p">)</span>
</code></pre></div></div>

<p>Then, it’s fairly typical unit testing for <code class="language-plaintext highlighter-rouge">init</code> and <code class="language-plaintext highlighter-rouge">update</code> (using <a href="https://fsprojects.github.io/FsUnit/">FsUnit</a> and <a href="https://nunit.org/">NUnit</a>).</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">open</span> <span class="nn">NUnit</span><span class="p">.</span><span class="nc">Framework</span>
<span class="k">open</span> <span class="nc">FsUnit</span>
<span class="k">open</span> <span class="nc">FabulousApp</span>
<span class="k">open</span> <span class="nn">Fabulous</span><span class="p">.</span><span class="nc">XamarinForms</span>

<span class="k">module</span> <span class="n">``Init tests``</span> <span class="p">=</span>
    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``Init should return a valid initial state``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">initialState</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">0</span> <span class="p">}</span>
        <span class="nn">App</span><span class="p">.</span><span class="n">init</span> <span class="bp">()</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="n">initialState</span>

<span class="k">module</span> <span class="n">``Update tests``</span> <span class="p">=</span>
    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``Given the message Increment, Update should increment Count``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">initialModel</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">5</span> <span class="p">}</span>
        <span class="k">let</span> <span class="n">expectedState</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">6</span> <span class="p">}</span>
        <span class="nn">App</span><span class="p">.</span><span class="n">update</span> <span class="nc">Increment</span> <span class="n">initialModel</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="n">expectedState</span>

    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``Given the message Decrement, Update should decrement Count``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">initialModel</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">5</span> <span class="p">}</span>
        <span class="k">let</span> <span class="n">expectedState</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">4</span> <span class="p">}</span>
        <span class="nn">App</span><span class="p">.</span><span class="n">update</span> <span class="nc">Decrement</span> <span class="n">initialModel</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="n">expectedState</span>
</code></pre></div></div>

<p>Testing <code class="language-plaintext highlighter-rouge">view</code> is a bit special.</p>

<p>Fabulous (dynamic views) stores your virtual view in a <code class="language-plaintext highlighter-rouge">ViewElement</code>, which is a glorified key-value dictionary.<br />
So, first we need to find our controls with the helper function <code class="language-plaintext highlighter-rouge">findViewElement</code> by providing it the previously declared AutomationIds.<br />
Then we feed the retrieved <code class="language-plaintext highlighter-rouge">ViewElement</code> to an helper class that will provide a nicely typed wrapper for a specific control.<br />
Each control has its matching <code class="language-plaintext highlighter-rouge">Viewer</code> helper class.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">module</span> <span class="n">``View tests``</span> <span class="p">=</span>
    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``View should generate a valid interface``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">model</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">5</span> <span class="p">}</span>
        <span class="k">let</span> <span class="n">actualView</span> <span class="p">=</span> <span class="nn">App</span><span class="p">.</span><span class="n">view</span> <span class="n">model</span> <span class="n">ignore</span>

        <span class="k">let</span> <span class="n">countLabel</span> <span class="p">=</span> <span class="n">actualView</span> <span class="p">|&gt;</span> <span class="n">findViewElement</span> <span class="s2">"CountLabel"</span> <span class="p">|&gt;</span> <span class="nc">LabelViewer</span>
        <span class="k">let</span> <span class="n">incrementButton</span> <span class="p">=</span> <span class="n">actualView</span> <span class="p">|&gt;</span> <span class="n">findViewElement</span> <span class="s2">"IncrementButton"</span> <span class="p">|&gt;</span> <span class="nc">ButtonViewer</span>
        <span class="k">let</span> <span class="n">decrementButton</span> <span class="p">=</span> <span class="n">actualView</span> <span class="p">|&gt;</span> <span class="n">findViewElement</span> <span class="s2">"DecrementButton"</span> <span class="p">|&gt;</span> <span class="nc">ButtonViewer</span>

        <span class="n">countLabel</span><span class="p">.</span><span class="nc">Text</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="s2">"5"</span>
        <span class="n">incrementButton</span><span class="p">.</span><span class="nc">Text</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="s2">"Increment"</span>
        <span class="n">decrementButton</span><span class="p">.</span><span class="nc">Text</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="s2">"Decrement"</span>

    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``Clicking the button Increment should send the message Increment``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">mockedDispatch</span> <span class="n">msg</span> <span class="p">=</span>
            <span class="n">msg</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="nc">Increment</span>

        <span class="k">let</span> <span class="n">model</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">5</span> <span class="p">}</span>
        <span class="k">let</span> <span class="n">actualView</span> <span class="p">=</span> <span class="nn">App</span><span class="p">.</span><span class="n">view</span> <span class="n">model</span> <span class="n">mockedDispatch</span>

        <span class="k">let</span> <span class="n">incrementButton</span> <span class="p">=</span> <span class="n">actualView</span> <span class="p">|&gt;</span> <span class="n">findViewElement</span> <span class="s2">"IncrementButton"</span> <span class="p">|&gt;</span> <span class="nc">ButtonViewer</span>

        <span class="n">incrementButton</span><span class="p">.</span><span class="nc">Command</span> <span class="bp">()</span>

    <span class="p">[&lt;</span><span class="nc">Test</span><span class="p">&gt;]</span>
    <span class="k">let</span> <span class="n">``Clicking the button Decrement should send the message Decrement``</span><span class="bp">()</span> <span class="p">=</span>
        <span class="k">let</span> <span class="n">mockedDispatch</span> <span class="n">msg</span> <span class="p">=</span>
            <span class="n">msg</span> <span class="p">|&gt;</span> <span class="n">should</span> <span class="n">equal</span> <span class="nc">Decrement</span>

        <span class="k">let</span> <span class="n">model</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Count</span> <span class="p">=</span> <span class="mi">5</span> <span class="p">}</span>
        <span class="k">let</span> <span class="n">actualView</span> <span class="p">=</span> <span class="nn">App</span><span class="p">.</span><span class="n">view</span> <span class="n">model</span> <span class="n">mockedDispatch</span>

        <span class="k">let</span> <span class="n">decrementButton</span> <span class="p">=</span> <span class="n">actualView</span> <span class="p">|&gt;</span> <span class="n">findViewElement</span> <span class="s2">"DecrementButton"</span> <span class="p">|&gt;</span> <span class="nc">ButtonViewer</span>

        <span class="n">decrementButton</span><span class="p">.</span><span class="nc">Command</span> <span class="bp">()</span>
</code></pre></div></div>

<h1 id="but-what-if-i-dont-want-to-use-xamarinforms">But what if I don’t want to use Xamarin.Forms?</h1>

<p>Fabulous.StaticView and AdaptiveFabulous are not currently meant to be used without Xamarin.Forms.<br />
If you really want the same static views experience with another framework, take a look at other existing libraries that do it really well, like <a href="https://github.com/elmish/Elmish.WPF">Elmish.WPF</a>.</p>

<p>Fabulous (dynamic views), on the other hand, is platform-agnostic meaning you can plug your favorite framework, at the condition you or someone else wrote the corresponding adapter library (with the appropriate control wrappers).</p>

<p>This is greatly simplified by <a href="https://github.com/fsprojects/Fabulous/tree/master/Fabulous.CodeGen">Fabulous.CodeGen</a> which will generate most of the code for you, if you provide it with the target framework dlls and instructions on what you want it to generate.<br />
This generated code can then be embedded in the adapter library.</p>

<p><a href="https://github.com/TimLariviere/Fabulous.WPF/blob/master/src/Fabulous.WPF/WPF.json">Example of the “Bindings” file</a> - <a href="https://github.com/TimLariviere/Fabulous.WPF/blob/master/src/Fabulous.WPF/WPF.fs">Example of the generated code</a></p>

<p><img src="/assets/2019-12-21-how-to-become-a-fabulous-developer/fabulous-codegen-workflow.svg" alt="Fabulous.CodeGen workflow" /></p>

<p>A few libraries are already making use of it:</p>
<ul>
  <li><a href="https://github.com/fsprojects/Fabulous/tree/master/Fabulous.XamarinForms">Fabulous.XamarinForms</a> for Xamarin.Forms</li>
  <li><a href="https://github.com/TimLariviere/Fabulous.WPF">Fabulous.WPF</a> for WPF (Proof of Concept)</li>
  <li><a href="https://github.com/TimLariviere/Fabulous.iOS">Fabulous.iOS</a> for Xamarin.iOS (Proof of Concept)</li>
  <li><a href="https://github.com/jeromelaban/Uno.Fabulous">Uno.Fabulous</a> for <a href="https://platform.uno/">Uno Platform</a> by Jérôme Laban (Proof of Concept)</li>
</ul>

<p>There are similar alternatives to Fabulous targeting other frameworks, like <a href="https://github.com/cmeeren/Elmish.WPF.Dynamic">Elmish.WPF.Dynamic</a> and <a href="https://github.com/FuncUI/Avalonia.FuncUI">Avalonia.FuncUI</a>.</p>

<h1 id="accelerating-the-development-process-with-liveupdate">Accelerating the development process with LiveUpdate</h1>

<p>Fabulous (dynamic views) has a tool called LiveUpdate, which is similar to Hot Reload (of React, Flutter and Xamarin.Forms).<br />
Just like Fabulous, LiveUpdate is technically compatible with all frameworks, though it will need an adapter for the specific framework you use.</p>

<p>With it, you can experience faster development feedback. After enabling it and starting a debug session (either on an emulator or an actual device), every time you make changes to the source code and save, the code is recompiled and injected in the running app. This allows you to quickly see the impact of your changes (1 to 2 seconds of wait), instead of stopping the app, rebuilding it, and once again debug.</p>

<p>To enable it, it’s really simple.<br />
You’ll need to install fabulous-cli if you haven’t already via the command line.</p>
<blockquote>
  <p>dotnet tool install -g fabulous-cli</p>
</blockquote>

<p>Then, add the corresponding NuGet package (here it’s <a href="https://www.nuget.org/packages/Fabulous.XamarinForms.LiveUpdate/">Fabulous.XamarinForms.LiveUpdate</a>) to all projects in the solution.<br />
After that, in your shared project (where your app code is), add the following lines after the declaration of the <code class="language-plaintext highlighter-rouge">runner</code>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">open</span> <span class="nn">Fabulous</span><span class="p">.</span><span class="nn">XamarinForms</span><span class="p">.</span><span class="nc">LiveUpdate</span>

<span class="p">#</span><span class="k">if</span> <span class="nc">DEBUG</span>
    <span class="k">do</span> <span class="n">runner</span><span class="p">.</span><span class="nc">EnableLiveUpdate</span> <span class="bp">()</span>
<span class="p">#</span><span class="n">endif</span>
</code></pre></div></div>

<p>When debugging, a message will be printed in the output window of your IDE.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>LiveUpdate: Ready for connection. Will show this message 3 more times.

LiveUpdate: Connect using:
   fabulous --watch --webhook:http://192.168.1.53:9867/update
</code></pre></div></div>

<p>Execute the given command line and you’re ready to go!</p>

<video height="420" controls="">
  <source src="/assets/2019-12-21-how-to-become-a-fabulous-developer/liveupdate.mov" type="video/mp4" />
</video>

<h1 id="whats-next">What’s next?</h1>

<p>The new way of writing apps using patterns like MVU and virtual views is getting a lot of traction recently. Well known frameworks like Elm, React-Redux or Flutter are making use of it. Even major actors want to provide their own (Apple with SwiftUI, Google with Android Jetpack Compose).</p>

<p>One thing to note is that such patterns are perfectly adapted to functional languages.</p>

<p>In the .NET world, Fabulous achieves this with F#.<br />
A really great language, an easy - reliable - maintainable architecture, an ultra-complete .NET ecosystem; perfect recipe for an awesome app!</p>

<p>Even more, Fabulous lets you choose the way you want to write your views with your framework of choice: static, dynamic or adaptive views.<br />
All that with useful tools like LiveUpdate.</p>

<p>For the future, we’re working on getting Fabulous to a v1.0 production ready release.<br />
We’re also working on adding more support for other frameworks, beyond Xamarin.Forms.</p>

<p>If you want to get started today, please read the documentation of your preferred way: <a href="https://fsprojects.github.io/Fabulous/Fabulous.StaticView/">static views</a>, <a href="https://fsprojects.github.io/Fabulous/Fabulous.XamarinForms/index.html#getting=started">dynamic views</a>, or <a href="https://github.com/dsyme/fabulous-adaptive">adaptive views</a>.</p>

<h1 id="contributing">Contributing</h1>

<p>If you’re interested to contribute to Fabulous, you can head to <a href="https://github.com/fsprojects/Fabulous">the Fabulous repository on GitHub</a>. There, you will be able to participate through issue reports, pull requests, code reviews and discussion.</p>

<p>Also if you want to stay updated, follow me on Twitter <a href="https://twitter.com/Tim_Lariviere">@Tim_Lariviere</a>.</p>

<p>I wish you a happy Christmas, and a lot of other awesome <a href="https://sergeytihon.com/2019/11/05/f-advent-calendar-in-english-2019/">#FsAdvent</a> posts!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[It’s the 21st day of the F# Advent Calendar 2019, only 4 days left before Christmas!]]></summary></entry><entry><title type="html">F# - Azure Cosmos DB - Using the Graph API with Cosmos DB driver</title><link href="/2018/04/04/f-azure-cosmos-db-using-the-graph-api-with-cosmos-db-driver/" rel="alternate" type="text/html" title="F# - Azure Cosmos DB - Using the Graph API with Cosmos DB driver" /><published>2018-04-04T00:00:00+00:00</published><updated>2018-04-04T00:00:00+00:00</updated><id>/2018/04/04/f-azure-cosmos-db-using-the-graph-api-with-cosmos-db-driver</id><content type="html" xml:base="/2018/04/04/f-azure-cosmos-db-using-the-graph-api-with-cosmos-db-driver/"><![CDATA[<p><em>The full sample can be found on Github : <a href="https://github.com/TimLariviere/Sample-FSharp-AzureCosmosDb">https://github.com/TimLariviere/Sample-FSharp-AzureCosmosDb</a></em></p>

<p>Setting up a graph database is really easy thanks to Azure Cosmos DB. Azure Cosmos DB is a multi-model database hosted on Microsoft Azure with lots of cool features such as a Graph API (with support for the popular Gremlin language) and turn-key worldwide distribution. For more information on Azure Cosmos DB, <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction">head to the documentation</a>.</p>

<p>In this post, I will show you how to make a .NET Core app written in F# that will use the Graph API of Azure Cosmos DB.</p>

<h3 id="azure-cosmos-db-graph-sdk">Azure Cosmos DB Graph SDK</h3>

<p>Microsoft made an SDK to interact with the Graph API, available on NuGet : <a href="https://www.nuget.org/packages/Microsoft.Azure.Graphs">Microsoft.Azure.Graphs</a> It’s currently in preview, so to find it, you’ll have to make sure to enable preview versions.</p>

<p>This SDK contains methods for most of the things we’ll need for the graph database. It handles connecting to it, querying it, and even dynamically creating new graphs.</p>

<p>It comes with its own Gremlin driver (the thing that handles the connection). That’s what I call the Cosmos DB driver. It has some limitations compared to the Gremlin.NET driver (for instance, named parameters are missing). I will explain how to use Gremlin.NET instead in a next post.</p>

<p>Before we’re able to use the SDK, we’ll need some configuration from the Azure portal.</p>

<h3 id="getting-the-configuration-parameters">Getting the configuration parameters</h3>

<p>Creating a new Azure Cosmos DB resource on the Azure portal is really simple. Just select “Azure Cosmos DB account”, click “Create” and fill out the form (and make sure to select “Gremlin (graph)”)</p>

<p><img src="/assets/2018-04-04-f-azure-cosmos-db-using-the-graph-api-with-cosmos-db-driver/CreateAzureCosmosDbAccount.png" alt="" /></p>

<p>Wait until Azure is done creating the resource.</p>

<p>To use the SDK, we will need the following values :</p>

<ul>
  <li>Endpoint</li>
  <li>AuthKey</li>
  <li>DatabaseName</li>
  <li>GraphName</li>
  <li>OfferThroughput</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">Endpoint</code> and <code class="language-plaintext highlighter-rouge">AuthKey</code> can be found in the <code class="language-plaintext highlighter-rouge">Keys</code> tab. <code class="language-plaintext highlighter-rouge">Endpoint</code> is the URI field and <code class="language-plaintext highlighter-rouge">AuthKey</code> is either the Primary or Secondary Key.
<img src="/assets/2018-04-04-f-azure-cosmos-db-using-the-graph-api-with-cosmos-db-driver/Keys.png" alt="" /></p>

<p>For the last 3 parameters, <code class="language-plaintext highlighter-rouge">DatabaseName</code> will be the name of the database (much like a database server in SQL Server) that will contain the graphs (the real databases). <code class="language-plaintext highlighter-rouge">GraphName</code> will be the name of our graph, and <code class="language-plaintext highlighter-rouge">OfferThroughput</code> is an indicator of the level of service you want for your graph (measured in Request Units per second, each request has its own RU cost).</p>

<p>For the sample, we’ll go with <code class="language-plaintext highlighter-rouge">DatabaseName = "sample-cosmosdb-database"</code>, <code class="language-plaintext highlighter-rouge">GraphName = "sample-cosmosdb-graph"</code> and <code class="language-plaintext highlighter-rouge">OfferThroughput = 400</code> (the minimum). We’ll store those settings in a json file named appsettings.json that our app will read.</p>

<p><em>appsettings.json</em></p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
    <span class="dl">"</span><span class="s2">AzureCosmosDb</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
        <span class="dl">"</span><span class="s2">Endpoint</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">https://[YOUR-AZURECOSMOSDB-ACCOUNT-NAME].documents.azure.com:443/</span><span class="dl">"</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">AuthKey</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">[YOUR-PRIMARY-KEY]</span><span class="dl">"</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">DatabaseName</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">sample-cosmosdb-database</span><span class="dl">"</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">GraphName</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">sample-cosmosdb-graph</span><span class="dl">"</span><span class="p">,</span>
        <span class="dl">"</span><span class="s2">OfferThroughput</span><span class="dl">"</span> <span class="p">:</span> <span class="mi">400</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="creating-the-project">Creating the project</h3>

<p>Making a .NET Core app in F# is as simple as running a single command line: (Of course, you can also create the project using Visual Studio) <code class="language-plaintext highlighter-rouge">dotnet new console -lang F# -n AzureCosmosDbSample</code></p>

<p>This creates 2 files (<code class="language-plaintext highlighter-rouge">AzureCosmosDbSample.fsproj</code> and <code class="language-plaintext highlighter-rouge">Program.fs</code>) for a working Hello world console in F#/.NET Core.</p>

<p>Before going on, we will need a few NuGet packages:</p>

<ul>
  <li><a href="https://www.nuget.org/packages/Microsoft.Azure.Graphs">Microsoft.Azure.Graphs</a>: Obviously</li>
  <li><a href="https://www.nuget.org/packages/FSharp.Control.AsyncSeq">FSharp.Control.AsyncSeq</a>: We will use it to asynchronously retrieve the query results</li>
  <li><a href="https://www.nuget.org/packages/Microsoft.Extensions.Configuration.Json">Microsoft.Extensions.Configuration.Json</a>: To read our settings file</li>
  <li><a href="https://www.nuget.org/packages/FSharp.Core">FSharp.Core</a>: <a href="https://fsharp.github.io/2015/04/18/fsharp-core-notes.html#always-reference-fsharpcore-via-the-nuget-package">Because you should always reference it explicitly</a></li>
</ul>

<p>Add the latest version of each using the NuGet GUI of Visual Studio, or if you prefer command lines:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dotnet add package Microsoft.Azure.Graphs -v 0.3.1-preview
dotnet add package FSharp.Control.AsyncSeq -v 2.0.21
dotnet add package Microsoft.Extensions.Configuration.Json -v 2.0.1
dotnet add package FSharp.Core -v 4.3.4
</code></pre></div></div>

<p>Now we can start writing code in the <code class="language-plaintext highlighter-rouge">Program.fs</code> file.</p>

<h3 id="using-the-azure-cosmos-db-sdk">Using the Azure Cosmos DB SDK</h3>

<p>The key class in the Azure Cosmos DB SDK is <code class="language-plaintext highlighter-rouge">DocumentClient</code>, so let’s make a function to instantiate it. The constructor takes our previously defined <code class="language-plaintext highlighter-rouge">Endpoint</code> and <code class="language-plaintext highlighter-rouge">AuthKey</code>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">createClient</span> <span class="n">endpoint</span> <span class="p">(</span><span class="n">authKey</span><span class="p">:</span> <span class="kt">string</span><span class="p">)</span> <span class="p">=</span>
    <span class="k">new</span> <span class="nc">DocumentClient</span><span class="p">(</span>
        <span class="k">new</span> <span class="nc">Uri</span><span class="p">(</span><span class="n">endpoint</span><span class="o">),</span>
        <span class="n">authKey</span><span class="p">,</span>
        <span class="nn">ConnectionPolicy</span><span class="p">.</span><span class="nc">Default</span>
    <span class="p">)</span>
</code></pre></div></div>

<p>Next, as we didn’t created the database and graph manually, we need to ensure that the database is properly created before querying the graph. Lucky for us, <code class="language-plaintext highlighter-rouge">DocumentClient</code> has a <code class="language-plaintext highlighter-rouge">CreateDatabaseIfNotExistsAsync</code> method that takes only our configured <code class="language-plaintext highlighter-rouge">DatabaseName</code>. Note that the code below doesn’t return the database. That’s because the database instance is not required to run queries.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">createDatabaseAsync</span> <span class="n">databaseName</span> <span class="p">(</span><span class="n">client</span><span class="p">:</span> <span class="nc">DocumentClient</span><span class="p">)</span> <span class="p">=</span>
    <span class="k">new</span> <span class="nc">Database</span> <span class="p">(</span><span class="nc">Id</span> <span class="p">=</span> <span class="n">databaseName</span><span class="p">)</span>
    <span class="p">|&gt;</span> <span class="n">client</span><span class="p">.</span><span class="nc">CreateDatabaseIfNotExistsAsync</span>
    <span class="p">|&gt;</span> <span class="nn">Async</span><span class="p">.</span><span class="nc">AwaitTask</span>
    <span class="p">|&gt;</span> <span class="nn">Async</span><span class="p">.</span><span class="nc">Ignore</span>
</code></pre></div></div>

<p>Same goes for the graph (using <code class="language-plaintext highlighter-rouge">CreateDocumentCollectionIfNotExistsAsync</code>). Except this time, we need to return the graph’s instance to be able to run queries afterwards.</p>

<p>We provide our <code class="language-plaintext highlighter-rouge">DatabaseName</code>, <code class="language-plaintext highlighter-rouge">GraphName</code>, and <code class="language-plaintext highlighter-rouge">OfferThroughput</code>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">createGraphAsync</span> <span class="n">databaseName</span> <span class="n">graphName</span> <span class="n">offerThroughput</span> <span class="p">(</span><span class="n">client</span><span class="p">:</span> <span class="nc">DocumentClient</span><span class="p">)</span> <span class="p">=</span>
    <span class="k">let</span> <span class="n">throughput</span> <span class="p">=</span> <span class="nc">Nullable</span><span class="p">&lt;</span><span class="kt">int</span><span class="o">&gt;(</span><span class="n">offerThroughput</span><span class="p">)</span>
    
    <span class="n">client</span><span class="p">.</span><span class="nc">CreateDocumentCollectionIfNotExistsAsync</span><span class="p">(</span>
        <span class="nn">UriFactory</span><span class="p">.</span><span class="nc">CreateDatabaseUri</span><span class="p">(</span><span class="n">databaseName</span><span class="o">),</span>
        <span class="k">new</span> <span class="nc">DocumentCollection</span> <span class="p">(</span><span class="nc">Id</span> <span class="p">=</span> <span class="n">graphName</span><span class="o">),</span>
        <span class="k">new</span> <span class="nc">RequestOptions</span> <span class="p">(</span><span class="nc">OfferThroughput</span> <span class="p">=</span> <span class="n">throughput</span><span class="p">)</span>
    <span class="p">)</span>
    <span class="p">|&gt;</span> <span class="nn">Async</span><span class="p">.</span><span class="nc">AwaitTask</span>
    <span class="p">|&gt;</span> <span class="p">(</span><span class="k">fun</span> <span class="n">asyncResult</span> <span class="p">-&gt;</span> <span class="n">async</span> <span class="p">{</span> <span class="k">let</span><span class="o">!</span> <span class="n">result</span> <span class="p">=</span> <span class="n">asyncResult</span> <span class="k">return</span> <span class="n">result</span><span class="p">.</span><span class="nc">Resource</span> <span class="o">})</span>
</code></pre></div></div>

<p>And now for the crucial part, running queries. Queries are made by calling <code class="language-plaintext highlighter-rouge">client.CreateGremlinQuery</code> with the previously created client, graph and the actual Gremlin request (as a string). This returns a Reader that exposes <code class="language-plaintext highlighter-rouge">ExecuteNextAsync</code> to get the next page of results. To ease its usage, the call to <code class="language-plaintext highlighter-rouge">ExecuteNextAsync</code> is wrapped into an asynchronous sequence. So enumerating that sequence will give all the query’s results, in an asynchronous manner.</p>

<p>Note that <code class="language-plaintext highlighter-rouge">ExecuteNextAsync</code> is generic. Behind the scene, every results retrieved from Azure Cosmos DB (sent as a JSON payload, known as <a href="http://tinkerpop.apache.org/docs/current/reference/#graphson-reader-writer">GraphSON</a>) will be converted to the given type via Newtonsoft.Json. The SDK already has some predefined types for that task, such as <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.graphs.elements">Vertex and Edge</a>.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">runGremlinQuery</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="p">&gt;</span> <span class="p">(</span><span class="n">dq</span><span class="p">:</span> <span class="nc">IDocumentQuery</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="o">&gt;)</span> <span class="p">=</span>
    <span class="n">asyncSeq</span> <span class="p">{</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">dq</span><span class="p">.</span><span class="nc">HasMoreResults</span><span class="p">)</span> <span class="k">do</span>
            <span class="k">let</span><span class="o">!</span> <span class="n">items</span> <span class="p">=</span> <span class="n">dq</span><span class="p">.</span><span class="nc">ExecuteNextAsync</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="o">&gt;()</span>
                         <span class="p">|&gt;</span> <span class="nn">Async</span><span class="p">.</span><span class="nc">AwaitTask</span>
            
            <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">items</span> <span class="k">do</span>
                <span class="k">yield</span> <span class="n">item</span>
    <span class="p">}</span>

<span class="k">let</span> <span class="n">runQueryWithClient</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="p">&gt;</span> <span class="p">(</span><span class="n">client</span><span class="p">:</span> <span class="nc">DocumentClient</span><span class="p">)</span> <span class="n">graph</span> <span class="n">query</span> <span class="p">=</span>
    <span class="n">client</span><span class="p">.</span><span class="nc">CreateGremlinQuery</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="o">&gt;(</span><span class="n">graph</span><span class="p">,</span> <span class="n">query</span><span class="p">)</span>
    <span class="p">|&gt;</span> <span class="n">runGremlinQuery</span><span class="p">&lt;</span><span class="k">'</span><span class="nc">T</span><span class="p">&gt;</span>
</code></pre></div></div>

<p>Last step, read our settings file using Microsoft.Extensions.Configuration.Json.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">AzureCosmosDbConfiguration</span> <span class="p">=</span>
    <span class="p">{</span> <span class="nc">Endpoint</span><span class="p">:</span> <span class="kt">string</span>
      <span class="nc">AuthKey</span><span class="p">:</span> <span class="kt">string</span>
      <span class="nc">DatabaseName</span><span class="p">:</span> <span class="kt">string</span>
      <span class="nc">GraphName</span><span class="p">:</span> <span class="kt">string</span>
      <span class="nc">OfferThroughput</span><span class="p">:</span> <span class="kt">int</span> <span class="p">}</span>

<span class="k">let</span> <span class="n">getConfiguration</span><span class="bp">()</span> <span class="p">=</span>
    <span class="nc">ConfigurationBuilder</span><span class="bp">()</span>
        <span class="p">.</span><span class="nc">SetBasePath</span><span class="p">(</span><span class="nn">Directory</span><span class="p">.</span><span class="nc">GetCurrentDirectory</span><span class="bp">()</span><span class="p">)</span>
        <span class="p">.</span><span class="nc">AddJsonFile</span><span class="p">(</span><span class="s2">"appsettings.json"</span><span class="p">)</span>
        <span class="p">.</span><span class="nc">Build</span><span class="bp">()</span>

<span class="k">let</span> <span class="n">readAzureCosmosDbConfiguration</span> <span class="p">(</span><span class="n">configuration</span><span class="p">:</span> <span class="nc">IConfigurationRoot</span><span class="p">)</span> <span class="p">=</span>
    <span class="p">{</span> <span class="nc">Endpoint</span> <span class="p">=</span> <span class="n">configuration</span><span class="o">.[</span><span class="s2">"AzureCosmosDb:Endpoint"</span><span class="p">]</span>
      <span class="nc">AuthKey</span> <span class="p">=</span> <span class="n">configuration</span><span class="o">.[</span><span class="s2">"AzureCosmosDb:AuthKey"</span><span class="p">]</span>
      <span class="nc">DatabaseName</span> <span class="p">=</span> <span class="n">configuration</span><span class="o">.[</span><span class="s2">"AzureCosmosDb:DatabaseName"</span><span class="p">]</span>
      <span class="nc">GraphName</span> <span class="p">=</span> <span class="n">configuration</span><span class="o">.[</span><span class="s2">"AzureCosmosDb:GraphName"</span><span class="p">]</span>
      <span class="nc">OfferThroughput</span> <span class="p">=</span> <span class="p">(</span><span class="n">configuration</span><span class="o">.[</span><span class="s2">"AzureCosmosDb:OfferThroughput"</span><span class="p">]</span> <span class="p">|&gt;</span> <span class="kt">int</span><span class="p">)</span> <span class="p">}</span>
</code></pre></div></div>

<p>We have all our tooling ready, now we can move on and actually run the sample.</p>

<h3 id="running-the-sample">Running the sample</h3>

<p>First step is to initialize our environment.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Get the configuration</span>
<span class="k">let</span> <span class="n">configuration</span> <span class="p">=</span> <span class="n">getConfiguration</span><span class="bp">()</span> <span class="p">|&gt;</span> <span class="n">readAzureCosmosDbConfiguration</span>

<span class="c1">// Create the client</span>
<span class="k">let</span> <span class="n">client</span> <span class="p">=</span> <span class="n">createClient</span> <span class="n">configuration</span><span class="p">.</span><span class="nc">Endpoint</span> <span class="n">configuration</span><span class="p">.</span><span class="nc">AuthKey</span>

<span class="c1">// Ensure that the database is created</span>
<span class="k">do</span><span class="o">!</span> <span class="n">createDatabaseAsync</span> <span class="n">configuration</span><span class="p">.</span><span class="nc">DatabaseName</span> <span class="n">client</span>

<span class="c1">// Ensure that the graph is created</span>
<span class="c1">// and store its instance</span>
<span class="k">let</span><span class="o">!</span> <span class="n">graph</span> <span class="p">=</span>
    <span class="n">createGraphAsync</span>
        <span class="n">configuration</span><span class="p">.</span><span class="nc">DatabaseName</span>
        <span class="n">configuration</span><span class="p">.</span><span class="nc">GraphName</span>
        <span class="n">configuration</span><span class="p">.</span><span class="nc">OfferThroughput</span>
        <span class="n">client</span>
</code></pre></div></div>

<p>To have a code easier to read, I partially applied the call to <code class="language-plaintext highlighter-rouge">runQueryWithClient</code> to always use the same client and graph.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Prepare a query runner that won't</span>
<span class="c1">// return results</span>
<span class="k">let</span> <span class="n">executeQuery</span> <span class="p">=</span> <span class="n">runQueryWithClient</span><span class="p">&lt;</span><span class="n">obj</span><span class="p">&gt;</span> <span class="n">client</span> <span class="n">graph</span> <span class="o">&gt;&gt;</span> <span class="nn">AsyncSeq</span><span class="p">.</span><span class="n">iter</span> <span class="n">ignore</span>

<span class="c1">// Prepare a query runner that will</span>
<span class="c1">// return a list of vertices</span>
<span class="k">let</span> <span class="n">getVertices</span> <span class="p">=</span> <span class="n">runQueryWithClient</span><span class="p">&lt;</span><span class="nc">Vertex</span><span class="p">&gt;</span> <span class="n">client</span> <span class="n">graph</span> <span class="o">&gt;&gt;</span> <span class="nn">AsyncSeq</span><span class="p">.</span><span class="n">toListAsync</span>

<span class="c1">// Prepare a query runner that will</span>
<span class="c1">// return a single vertex</span>
<span class="k">let</span> <span class="n">getSingleVertex</span> <span class="p">=</span> <span class="n">getVertices</span> <span class="o">&gt;&gt;</span> <span class="nn">List</span><span class="p">.</span><span class="n">head</span>
</code></pre></div></div>

<p>Now we’re all done, and can start running our queries.</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Add data</span>
<span class="k">do</span><span class="o">!</span> <span class="n">executeQuery</span>
    <span class="s2">"g.addV('person')
      .property('id', 'thomas')
      .property('firstName', 'Thomas')
      .property('age', 44)"</span>

<span class="c1">// Retrieve data</span>
<span class="k">let</span><span class="o">!</span> <span class="n">thomas</span> <span class="p">=</span> <span class="n">getSingleVertex</span> <span class="s2">"g.V('thomas')"</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[The full sample can be found on Github : https://github.com/TimLariviere/Sample-FSharp-AzureCosmosDb]]></summary></entry><entry><title type="html">F# - Azure Functions - Using the correct FSharp.Core version</title><link href="/2018/03/24/f-azure-functions-using-the-correct-fsharp-core-version/" rel="alternate" type="text/html" title="F# - Azure Functions - Using the correct FSharp.Core version" /><published>2018-03-24T00:00:00+00:00</published><updated>2018-03-24T00:00:00+00:00</updated><id>/2018/03/24/f-azure-functions-using-the-correct-fsharp-core-version</id><content type="html" xml:base="/2018/03/24/f-azure-functions-using-the-correct-fsharp-core-version/"><![CDATA[<p>After deploying your beloved Azure Function written in F#, you might end up with the following exception when executing the function: <code class="language-plaintext highlighter-rouge">Could not load file or assembly 'FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies</code></p>

<p>But why such an exception? When running the function locally, all was fine.</p>

<p>That’s because when Azure runs your function, it runs it inside a process that is already using an older version of FSharp.Core. And when it tries to load the FSharp.Core.dll from the /bin folder, it fails. The F# Core Engineering team warns us about it: <a href="https://fsharp.github.io/2015/04/18/fsharp-core-notes.html#some-systems-supporting-f-eg-azure-functions-azure-notebooks-f-interactive-may-assume-a-fixed-fsharpcore">Some systems supporting F# (e.g. Azure Functions, Azure Notebooks, F# Interactive) may assume a fixed FSharp.Core</a></p>

<p>So what should you do? As of now, there’s no way to use a version of FSharp.Core higher than 4.4.1.0 (nuget version 4.2.3). The only way is to force NuGet to restore the FSharp.Core package 4.2.3.</p>

<p>If you’re using .NET Standard 2.0 and the new fsproj format, you should have the following project file:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">"Microsoft.NET.Sdk"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;PropertyGroup&gt;</span>
        <span class="nt">&lt;TargetFramework&gt;</span>netstandard2.0<span class="nt">&lt;/TargetFramework&gt;</span>
    <span class="nt">&lt;/PropertyGroup&gt;</span>
<span class="nt">&lt;/Project&gt;</span>
</code></pre></div></div>

<p>FSharp.Core is included by default when using <code class="language-plaintext highlighter-rouge">Microsoft.NET.Sdk</code> If you’re deploying from Mac, your function will run fine, but not if you’re deploying from Windows. That’s because the default FSharp.Core included is not the same.</p>

<p><em>Microsoft.FSharp.NetSdk.targets on Mac</em></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;PropertyGroup</span> <span class="na">Condition=</span><span class="s">" '$(FSharpCoreImplicitPackageVersion)' == '' "</span><span class="nt">&gt;</span>
    <span class="nt">&lt;FSharpCoreImplicitPackageVersion&gt;</span>4.2.*<span class="nt">&lt;/FSharpCoreImplicitPackageVersion&gt;</span>
<span class="nt">&lt;/PropertyGroup&gt;</span>
</code></pre></div></div>

<p><em>Microsoft.FSharp.NetSdk.targets on Windows</em></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;PropertyGroup</span> <span class="na">Condition=</span><span class="s">" '$(FSharpCoreImplicitPackageVersion)' == '' "</span><span class="nt">&gt;</span>
    <span class="nt">&lt;FSharpCoreImplicitPackageVersion&gt;</span>4.3.*<span class="nt">&lt;/FSharpCoreImplicitPackageVersion&gt;</span>
<span class="nt">&lt;/PropertyGroup&gt;</span>
</code></pre></div></div>

<p>To ensure that your function will run whatever OS you’re deploying from, just set the value of <code class="language-plaintext highlighter-rouge">FSharpCoreImplicitPackageVersion</code>.</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Project</span> <span class="na">Sdk=</span><span class="s">"Microsoft.NET.Sdk"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;PropertyGroup&gt;</span>
        <span class="nt">&lt;TargetFramework&gt;</span>netstandard2.0<span class="nt">&lt;/TargetFramework&gt;</span>
        <span class="nt">&lt;FSharpCoreImplicitPackageVersion&gt;</span>4.2.3<span class="nt">&lt;/FSharpCoreImplicitPackageVersion&gt;</span>
    <span class="nt">&lt;/PropertyGroup&gt;</span>
<span class="nt">&lt;/Project&gt;</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[After deploying your beloved Azure Function written in F#, you might end up with the following exception when executing the function: Could not load file or assembly 'FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies]]></summary></entry><entry><title type="html">Authenticate users through Facebook using Xamarin.Auth</title><link href="/2017/10/11/authenticate-users-through-facebook-using-xamarin-auth/" rel="alternate" type="text/html" title="Authenticate users through Facebook using Xamarin.Auth" /><published>2017-10-11T00:00:00+00:00</published><updated>2017-10-11T00:00:00+00:00</updated><id>/2017/10/11/authenticate-users-through-facebook-using-xamarin-auth</id><content type="html" xml:base="/2017/10/11/authenticate-users-through-facebook-using-xamarin-auth/"><![CDATA[<p>Following the previous post on Google authentication, I will now focus on how to authenticate on Facebook with Xamarin.Auth and retrieve the user’s email address. In case you missed the Google post, you can read all about it here: <a href="http://timothelariviere.com/2017/09/01/authenticate-users-through-google-with-xamarin-auth/">Authenticate users through Google with Xamarin.Auth</a></p>

<p>As previously, a sample is available on GitHub: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Facebook">https://github.com/TimLariviere/Sample-XamarinAuth-Facebook</a></p>

<h3 id="facebook-authentication-with-xamarinauth">Facebook authentication with Xamarin.Auth</h3>

<p>Unlike Google, Facebook doesn’t require us to use native SDKs to authenticate users. So we can let the IsUsingNativeUI flag of Xamarin.Auth disabled, which is hopeful because restrictions on the Redirect URL would have prevented us to enable it.</p>

<p>Facebook exclusively wants HTTP/HTTPS redirect URLs thus not allowing us to use the deep link technique as we’ve done in the previous post (well to be fair, we could but it would require us extra work).</p>

<p>With that in mind, configuring Facebook with Xamarin.Auth is essentially much simpler than Google.</p>

<h3 id="configuring-the-facebook-for-developers-portal">Configuring the Facebook for Developers portal</h3>

<p>Before starting, we’ll need to declare our app in the Facebook for Developers portal. Go to <a href="https://developers.facebook.com/apps">https://developers.facebook.com/apps</a></p>

<p>If you haven’t already, create a new App ID.
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/Create.png" alt="" /></p>

<p>Once created, we’ll need to enable the OAuth feature by adding Facebook Login to our app declaration. For that, click “+ Add Product” in the left menu and then set up Facebook Login.
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/AddFacebookLogin.png" alt="" /></p>

<p>There’s only one thing that we need to configure in Facebook Login: the redirect URL that we will use to let Xamarin.Auth know that the authentication flow has ended.</p>

<p>That Redirect URL can be any valid HTTP/HTTPS URLs, it’s just an indicator that the authentication has completed and won’t be visible to your users. Facebook provides a default URL that you can use: https://www.facebook.com/connect/login_success.html
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/Settings-1024x475.png" alt="" /></p>

<p>By default, our application is in development mode, only allowing members of our team (defined under Roles) to authenticate. Any other account will see a message stating that they can’t connect due to the development mode.
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/NotLive.png" alt="" /></p>

<p>If you want anyone to access your app, you’ll need to switch to production. There’s a switch for that under App Review.
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/Prod-1024x665.png" alt="" /></p>

<p>Notice that there’s already a few permissions given to our app including the authorization to retrieve the user’s email address. We’re lucky!</p>

<p>Make sure to note down the App ID as we’ll need it in our Xamarin apps.
<img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/AppId.png" alt="" /></p>

<p>And we’re done for the declaration part. Android and iOS will use the exact same configuration, so there’s nothing more to do.</p>

<h3 id="implementing-facebook-authentication-in-the-pcl-project">Implementing Facebook authentication in the PCL project</h3>

<h4 id="1-2-nuget-packages--using-xamarinauth">1-2. NuGet Packages &amp; Using Xamarin.Auth</h4>

<p>I won’t go into details here, as I’ve already described it on the previous post.</p>

<p>For the sake of this post, here’s the 2 packages we’ll need:</p>

<ul>
  <li><a href="https://www.nuget.org/packages/Xamarin.Auth/">Xamarin.Auth</a> (version used 1.5.0.3)</li>
  <li><a href="https://www.nuget.org/packages/Newtonsoft.Json/">Newtonsoft.Json</a> (version used 10.0.3)</li>
</ul>

<p>Like Google, Facebook authentication is done using OAuth2, so we will use the OAuth2Authenticator class provided by Xamarin.Auth. Facebook will automatically provide the Access Token once we’re authenticated, so there’s no need for an AccessTokenUrl.</p>

<p>This time, we will use this constructor signature.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nf">OAuth2Authenticator</span><span class="p">(</span>
    <span class="kt">string</span> <span class="n">clientId</span><span class="p">,</span>
    <span class="kt">string</span> <span class="n">scope</span><span class="p">,</span>
    <span class="n">Uri</span> <span class="n">authorizeUrl</span><span class="p">,</span>
    <span class="n">Uri</span> <span class="n">redirectUrl</span><span class="p">,</span>
    <span class="n">GetUsernameAsyncFunc</span> <span class="n">getUsernameAsyncFunc</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">isUsingNativeUI</span> <span class="p">=</span> <span class="k">false</span><span class="p">)</span>
</code></pre></div></div>

<ul>
  <li><strong>ClientId</strong>: the id of our app on the Facebook for Developers portal</li>
  <li><strong>Scope</strong>: magic string telling which permission to grant on authentication</li>
  <li><strong>AuthorizeUrl</strong>: Facebook’s URL required when authenticating</li>
  <li><strong>RedirectUrl</strong>: custom url (doesn’t need to exist)</li>
  <li><strong>GetUsernameAsyncFunc</strong>: we won’t be using it</li>
  <li><strong>IsUsingNativeUI</strong>: flag to use the device’s web browser instead of an embedded webview. We won’t be using it.</li>
</ul>

<p>Xamarin.Auth will query the AuthorizeUrl with our ClientId and Scope. Once the user is authenticated in his browser, Facebook will call our RedirectUrl with a bunch of parameters. Xamarin.Auth will catch this RedirectUrl and parse it.</p>

<p>The AuthorizeUrl should have the value “https://www.facebook.com/dialog/oauth/”, according to the <a href="https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/">Facebook documentation</a>. The Scope we will use is “email”. You can find the one you need in the <a href="https://developers.facebook.com/docs/facebook-login/permissions">Facebook documentation</a>.</p>

<p>If you need to use a specific version of the Facebook OAuth API, you can specify it in the URL (like this “https://www.facebook.com/v2.10/dialog/oauth/”). You can find the oldest version allowed on the Facebook for Developers portal, next to the App ID.</p>

<p>Here’s the result for my sample app:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">OAuth2Authenticator</span><span class="p">(</span>
    <span class="s">"1919579418305741"</span><span class="p">,</span>
    <span class="s">"email"</span><span class="p">,</span>
    <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">"https://www.facebook.com/dialog/oauth/"</span><span class="p">),</span>
    <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">"https://www.facebook.com/connect/login_success.html"</span><span class="p">));</span>
</code></pre></div></div>

<p>The OAuth2Authenticator class comes with two events: Completed and Error<br />
They’re quite simple to understand. The first one will call our handler when the authentication has completed (with the user authenticated or not) and the latter will allow us to react to an error (bad network, etc.)</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_auth</span><span class="p">.</span><span class="n">Completed</span> <span class="p">+=</span> <span class="n">OnAuthenticationCompleted</span><span class="p">;</span>
<span class="n">_auth</span><span class="p">.</span><span class="n">Error</span> <span class="p">+=</span> <span class="n">OnAuthenticationFailed</span><span class="p">;</span>
</code></pre></div></div>

<p>When the authentication ends, OnAuthenticationCompleted is called and we can check if the user is authenticated and retrieve the precious OAuth token that we need to call other APIs.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">AuthenticatorCompletedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">IsAuthenticated</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">token</span> <span class="p">=</span> <span class="k">new</span> <span class="n">FacebookOAuthToken</span>
        <span class="p">{</span>
            <span class="n">AccessToken</span> <span class="p">=</span> <span class="n">e</span><span class="p">.</span><span class="n">Account</span><span class="p">.</span><span class="n">Properties</span><span class="p">[</span><span class="s">"access_token"</span><span class="p">]</span>
        <span class="p">};</span>
        
        <span class="c1">// Do something</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
        <span class="c1">// The user is not authenticated</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>N.B.: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Facebook/blob/master/Xamarin-FacebookAuth/Xamarin_FacebookAuth/Authentication/FacebookOAuthToken.cs">FacebookOAuthToken</a> is part of the sample.</p>

<p>That’s all for our Facebook implementation.</p>

<p>For a more detailed implementation, you can find the whole <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Facebook/blob/master/Xamarin-FacebookAuth/Xamarin_FacebookAuth/Authentication/FacebookAuthenticator.cs">FacebookAuthenticator file</a> used in the sample.</p>

<h4 id="3-retrieving-the-users-email-address">3. Retrieving the user’s email address</h4>

<p>Now that we have our Access Token, we can simply call the Facebook Graph API to retrieve the user’s email address: https://graph.facebook.com/me?fields=email&amp;access_token=[ACCESS_TOKEN]</p>

<p>As you can see, Facebook requires the access token as a query param instead of an HTTP Authorization header.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="nf">GetEmailAsync</span><span class="p">(</span><span class="kt">string</span> <span class="n">accessToken</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">httpClient</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpClient</span><span class="p">();</span>
    
    <span class="kt">var</span> <span class="n">json</span> <span class="p">=</span> <span class="k">await</span> <span class="n">httpClient</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span>
        <span class="s">$"https://graph.facebook.com/me?fields=email&amp;access_token=</span><span class="p">{</span><span class="n">accessToken</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
    
    <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="n">DeserializeObject</span><span class="p">&lt;</span><span class="n">FacebookEmail</span><span class="p">&gt;(</span><span class="n">json</span><span class="p">);</span>
    
    <span class="k">return</span> <span class="n">email</span><span class="p">.</span><span class="n">Email</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>N.B.: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Facebook/blob/master/Xamarin-FacebookAuth/Xamarin_FacebookAuth/Services/FacebookEmail.cs">FacebookEmail</a> is also part of the sample.</p>

<p>And we’re done for the PCL part!</p>

<h3 id="implementing-facebook-authentication-in-the-android-project">Implementing Facebook authentication in the Android project</h3>

<h4 id="1-installing-nuget-packages">1. Installing NuGet packages</h4>

<p>This is the part where Facebook with Xamarin.Auth is way simpler to set up than Google. Facebook didn’t asked for our package name, so it is not a required part of the sample (of course, set up your app’s package name when going for production).</p>

<p>As we don’t use the IsUsingNativeUI flag, there’s no need to update the CustomTabs Support Library and set up redirection interceptors.</p>

<p>All we have to do here is to install the Xamarin.Auth package to our Android project. N.B.: In case you plan to integrate Google login to your app later, follow the Google post instead.</p>

<h4 id="2-running-our-project">2. Running our project</h4>

<p>All that is left is to run the authenticator. By calling GetUI and StartActivity, we will tell Xamarin.Auth to display a webview to let the users authenticate.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// "this" is the current activity</span>
<span class="kt">var</span> <span class="n">intent</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
<span class="nf">StartActivity</span><span class="p">(</span><span class="n">intent</span><span class="p">);</span>
</code></pre></div></div>

<p>In order to make it easier to reuse the FacebookAuthenticator class from the sample, I’ve extracted the ClientId and Scope in a configuration file that I’ve put into the PCL project. Here’s the configuration I’ll be using for both Android and iOS</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Configuration</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">ClientId</span> <span class="p">=</span> <span class="s">"1919579418305741"</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Scope</span> <span class="p">=</span> <span class="s">"email"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And we can finally integrate Facebook in our Android app.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nf">Activity</span> <span class="p">(</span><span class="n">Label</span> <span class="p">=</span> <span class="s">"Xamarin_FacebookAuth.Android"</span><span class="p">,</span> <span class="n">MainLauncher</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span> <span class="n">Icon</span> <span class="p">=</span> <span class="s">"@drawable/icon"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">Activity</span><span class="p">,</span> <span class="n">IFacebookAuthenticationDelegate</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="n">FacebookAuthenticator</span> <span class="n">_auth</span><span class="p">;</span>
    
    <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnCreate</span><span class="p">(</span><span class="n">Bundle</span> <span class="n">bundle</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">OnCreate</span><span class="p">(</span><span class="n">bundle</span><span class="p">);</span>
        
        <span class="nf">SetContentView</span><span class="p">(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Layout</span><span class="p">.</span><span class="n">Main</span><span class="p">);</span>
        
        <span class="n">_auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">FacebookAuthenticator</span><span class="p">(</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">ClientId</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">Scope</span><span class="p">,</span>
            <span class="k">this</span><span class="p">);</span>
            
        <span class="kt">var</span> <span class="n">facebookLoginButton</span> <span class="p">=</span>
            <span class="n">FindViewById</span><span class="p">&lt;</span><span class="n">Button</span><span class="p">&gt;(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Id</span><span class="p">.</span><span class="n">facebookLoginButton</span><span class="p">);</span>
            
        <span class="n">facebookLoginButton</span><span class="p">.</span><span class="n">Click</span> <span class="p">+=</span> <span class="n">OnFacebookLoginButtonClicked</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">private</span> <span class="k">void</span> <span class="nf">OnFacebookLoginButtonClicked</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// Display the activity handling the authentication</span>
        <span class="kt">var</span> <span class="n">authenticator</span> <span class="p">=</span> <span class="n">_auth</span><span class="p">.</span><span class="nf">GetAuthenticator</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">intent</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
        <span class="nf">StartActivity</span><span class="p">(</span><span class="n">intent</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">async</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span><span class="n">FacebookOAuthToken</span> <span class="n">token</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// Retrieve the user's email address</span>
        <span class="kt">var</span> <span class="n">facebookService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">FacebookService</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span> <span class="k">await</span> <span class="n">facebookService</span><span class="p">.</span><span class="nf">GetEmailAsync</span><span class="p">(</span><span class="n">token</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
        
        <span class="c1">// Display it on the UI</span>
        <span class="kt">var</span> <span class="n">facebookButton</span> <span class="p">=</span>
            <span class="n">FindViewById</span><span class="p">&lt;</span><span class="n">Button</span><span class="p">&gt;(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Id</span><span class="p">.</span><span class="n">facebookLoginButton</span><span class="p">);</span>
            
        <span class="n">facebookButton</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="s">$"Connected with </span><span class="p">{</span><span class="n">email</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationCanceled</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="n">AlertDialog</span><span class="p">.</span><span class="nf">Builder</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetTitle</span><span class="p">(</span><span class="s">"Authentication canceled"</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetMessage</span><span class="p">(</span><span class="s">"You didn't completed the authentication process"</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">Show</span><span class="p">();</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationFailed</span><span class="p">(</span><span class="kt">string</span> <span class="n">message</span><span class="p">,</span> <span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="n">AlertDialog</span><span class="p">.</span><span class="nf">Builder</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetTitle</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetMessage</span><span class="p">(</span><span class="n">exception</span><span class="p">?.</span><span class="nf">ToString</span><span class="p">())</span>
            <span class="p">.</span><span class="nf">Show</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><img src="/assets/2017-10-10-authenticate-users-through-facebook-using-xamarin-auth/FacebookAndroid.png" alt="" /></p>

<h3 id="implementing-facebook-authentication-in-the-ios-project">Implementing Facebook authentication in the iOS project</h3>

<h4 id="1-installing-nuget-packages-1">1. Installing NuGet packages</h4>

<p>Same as Android, just install the Xamarin.Auth package to our iOS project.</p>

<h4 id="2-running-our-project-1">2. Running our project</h4>

<p>Same as Android, we run the actual authenticator.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">viewController</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">();</span>
<span class="nf">PresentViewController</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
</code></pre></div></div>

<p>Also when you’re handling both Completed and Error events from the authenticator, you will need to manually call DismissViewController because Xamarin.Auth won’t dismiss the webview itself.</p>

<p>And we glue everything together, this time for iOS!</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">ViewController</span> <span class="p">:</span> <span class="n">UIViewController</span><span class="p">,</span> <span class="n">IFacebookAuthenticationDelegate</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="nf">ViewController</span><span class="p">(</span><span class="n">IntPtr</span> <span class="n">handle</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span> <span class="p">(</span><span class="n">handle</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>
        
    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">ViewDidLoad</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">ViewDidLoad</span><span class="p">();</span>
        
        <span class="n">FacebookLoginButton</span><span class="p">.</span><span class="n">TouchUpInside</span> <span class="p">+=</span> <span class="n">OnFacebookLoginButtonClicked</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">private</span> <span class="k">void</span> <span class="nf">OnFacebookLoginButtonClicked</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">FacebookAuthenticator</span><span class="p">(</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">ClientId</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">Scope</span><span class="p">,</span>
            <span class="k">this</span><span class="p">);</span>
            
        <span class="kt">var</span> <span class="n">authenticator</span> <span class="p">=</span> <span class="n">auth</span><span class="p">.</span><span class="nf">GetAuthenticator</span><span class="p">();</span>
        
        <span class="kt">var</span> <span class="n">viewController</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">();</span>
        
        <span class="nf">PresentViewController</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">async</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span><span class="n">FacebookOAuthToken</span> <span class="n">token</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nf">DismissViewController</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
        
        <span class="kt">var</span> <span class="n">facebookService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">FacebookService</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span> <span class="k">await</span> <span class="n">facebookService</span><span class="p">.</span><span class="nf">GetEmailAsync</span><span class="p">(</span><span class="n">token</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
        
        <span class="n">FacebookLoginButton</span><span class="p">.</span><span class="nf">SetTitle</span><span class="p">(</span> <span class="s">$"Connected with </span><span class="p">{</span><span class="n">email</span><span class="p">}</span><span class="s">"</span><span class="p">,</span> <span class="n">UIControlState</span><span class="p">.</span><span class="n">Normal</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationFailed</span><span class="p">(</span><span class="kt">string</span> <span class="n">message</span><span class="p">,</span> <span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="nf">DismissViewController</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
        
        <span class="kt">var</span> <span class="n">alertController</span> <span class="p">=</span> <span class="k">new</span> <span class="n">UIAlertController</span>
        <span class="p">{</span>
            <span class="n">Title</span> <span class="p">=</span> <span class="n">message</span><span class="p">,</span>
            <span class="n">Message</span> <span class="p">=</span> <span class="n">exception</span><span class="p">?.</span><span class="nf">ToString</span><span class="p">()</span>
        <span class="p">};</span>
        
        <span class="nf">PresentViewController</span><span class="p">(</span><span class="n">alertController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationCanceled</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nf">DismissViewController</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
        
        <span class="kt">var</span> <span class="n">alertController</span> <span class="p">=</span> <span class="k">new</span> <span class="n">UIAlertController</span>
        <span class="p">{</span>
            <span class="n">Title</span> <span class="p">=</span> <span class="s">"Authentication canceled"</span>
            <span class="n">Message</span> <span class="p">=</span> <span class="s">"You didn't completed the authentication process"</span>
        <span class="p">};</span>
        
        <span class="nf">PresentViewController</span><span class="p">(</span><span class="n">alertController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[Following the previous post on Google authentication, I will now focus on how to authenticate on Facebook with Xamarin.Auth and retrieve the user’s email address. In case you missed the Google post, you can read all about it here: Authenticate users through Google with Xamarin.Auth]]></summary></entry><entry><title type="html">Authenticate users through Google with Xamarin.Auth</title><link href="/2017/09/01/authenticate-users-through-google-with-xamarin-auth/" rel="alternate" type="text/html" title="Authenticate users through Google with Xamarin.Auth" /><published>2017-09-01T00:00:00+00:00</published><updated>2017-09-01T00:00:00+00:00</updated><id>/2017/09/01/authenticate-users-through-google-with-xamarin-auth</id><content type="html" xml:base="/2017/09/01/authenticate-users-through-google-with-xamarin-auth/"><![CDATA[<p>I’ve recently worked on a Xamarin app that needed to authenticate its users against Facebook, Google, and Twitter, and needed to retrieve their email addresses. <a href="https://github.com/xamarin/Xamarin.Auth">Xamarin.Auth</a> did the heavy lifting for us, handling all the OAuth authentication flow. But configuring it for Facebook, Google, and Twitter can be complicated as their configurations are (not so) slightly different.</p>

<p>After quite a bit of struggle, I decided to share every single steps that led me to successfully implement authentication and getting the user’s email address.</p>

<p>In this post, I will focus on integrating Google authentication in your app.</p>

<p>If you’re eager to see some code, here is a sample app: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Google">https://github.com/TimLariviere/Sample-XamarinAuth-Google</a></p>

<h3 id="google-authentication-with-xamarinauth">Google authentication with Xamarin.Auth</h3>

<p>Previously Google allowed the use of in-app webviews to handle the authentication flow, like what Facebook and Twitter do. But at the start of the year, Google changed its policy for native apps.</p>

<p>It now requires the use of native browsers through libraries (CustomTabs on Android and SFSafariViewController on iOS) Xamarin.Auth uses by default an in-app webview, but it also supports CustomTabs/SFSafariViewController by enabling the IsUsingNativeUI flag. While it is fully supported, it can be quite complex to compile and run successfully.</p>

<h3 id="configuring-the-google-developer-console">Configuring the Google Developer Console</h3>

<p>Before coding, we first need to properly declare a new project in the Google Developer Console to get the identifiers required by Xamarin.Auth.</p>

<p>For that, go to <a href="https://console.developers.google.com">https://console.developers.google.com</a></p>

<p>There, you will be able to create a new project. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/01-CreateProject.png" alt="" /></p>

<p>Once it’s done, go to “Credentials” and configure the “OAuth consent screen”. You will need to set at least the “Product name shown to users”, otherwise Google won’t let you create keys for Android and iOS. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/02-ConsentScreen.png" alt="" /></p>

<p>Now we need two OAuth client ID, one for each platform. The information needed differs from Android and iOS.</p>

<p>Let’s look at Android first. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/04-AndroidCreateOAuthClientId.png" alt="" /></p>

<ul>
  <li>Name: It can be anything you want</li>
  <li>Signing-certificate fingerprint: the SHA-1 fingerprint of your keystore certificate that will sign your APK</li>
  <li>Package name: the package name of your app</li>
</ul>

<p>You can find the signing-certificate fingerprint using the command shown. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/05-AndroidKeystoreSha1.png" alt="" /></p>

<p>You will need as many OAuth Client ID as you have Keystore files to sign your app (Debug, Production, etc.).</p>

<p>For iOS, it’s a little simpler. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/06-iOSCreateOAuthClientId.png" alt="" /></p>

<ul>
  <li>Name: It can be anything you want</li>
  <li>Bundle ID: the package name of your app</li>
  <li>App Store ID: the id of your app on the App Store</li>
  <li>Team ID: the id of your team on developer.apple.com</li>
</ul>

<p>The last two fields are optional and allow you to retrict the usage of the OAuth Client ID to only your app.</p>

<p>Upon creation, Google will give you the client IDs that we need. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/06bis-OAuthClientIds.png" alt="" /></p>

<p>And that’s all for the Google Developer Console part. Let’s see how to actually implement Xamarin.Auth in a PCL library, shared by Android and iOS.</p>

<h3 id="implementing-google-authentication-in-the-pcl-project">Implementing Google authentication in the PCL project</h3>

<h4 id="1-installing-the-nuget-packages">1. Installing the NuGet packages</h4>

<p>First, we’ll need to add the <a href="https://www.nuget.org/packages/Xamarin.Auth/">Xamarin.Auth NuGet package</a> to our PCL project. For this sample, I’ve downloaded the latest version on NuGet which is 1.5.0.3. <img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/XamarinAuth.png" alt="" /></p>

<p>Then, as we plan on getting the user’s email address, we’ll need to call some REST APIs that will reply in JSON. Just add a reference to the latest <a href="https://www.nuget.org/packages/Newtonsoft.Json/">Newtonsoft.Json package</a> (10.0.3 at the time of writing).</p>

<h4 id="2-using-xamarinauth">2. Using Xamarin.Auth</h4>

<p>As Google authentication is OAuth2, we will use the OAuth2Authenticator class provided by Xamarin.Auth. This class comes with several constructors but only one interests us.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nf">OAuth2Authenticator</span><span class="p">(</span>
    <span class="kt">string</span> <span class="n">clientId</span><span class="p">,</span>
    <span class="kt">string</span> <span class="n">clientSecret</span><span class="p">,</span>
    <span class="kt">string</span> <span class="n">scope</span><span class="p">,</span>
    <span class="n">Uri</span> <span class="n">authorizeUrl</span><span class="p">,</span>
    <span class="n">Uri</span> <span class="n">redirectUrl</span><span class="p">,</span>
    <span class="n">Uri</span> <span class="n">accessTokenUrl</span><span class="p">,</span>
    <span class="n">GetUsernameAsyncFunc</span> <span class="n">getUsernameAsyncFunc</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span>
    <span class="kt">bool</span> <span class="n">isUsingNativeUI</span> <span class="p">=</span> <span class="k">false</span><span class="p">);</span>
</code></pre></div></div>

<ul>
  <li><strong>ClientId</strong>: the id that we’ve generated on Google Developer Console (Android/iOS)</li>
  <li><strong>ClientSecret</strong>: not needed by Google</li>
  <li><strong>Scope</strong>: magic string telling which permission to grant on authentication</li>
  <li><strong>AuthorizeUrl/AccessTokenUrl</strong>: Google’s URLs required when authenticating</li>
  <li><strong>RedirectUrl</strong>: custom url (doesn’t need to exist)</li>
  <li><strong>GetUsernameAsyncFunc</strong>: we won’t be using it</li>
  <li><strong>IsUsingNativeUI</strong>: the famous flag to enable in order to comply to Google’s new policy</li>
</ul>

<p>Xamarin.Auth will query the AuthorizeUrl with our ClientId and Scope. Then, when the user will be authenticated in his web browser, Google will call our RedirectUrl with a bunch of parameters. Xamarin.Auth will catch this RedirectUrl (with our help, we’ll see that later) and parse it. Then it will call the AccessTokenUrl to get the actual token that will allow us to call APIs as the authenticated user.</p>

<p>AuthorizeUrl and AccessTokenUrl can be retrieved in the <a href="https://developers.google.com/identity/protocols/OAuth2InstalledApp">Google documentation</a>. The Scope can be also retrieved in the <a href="https://developers.google.com/identity/protocols/googlescopes">Google documentation</a>. Though we will use the “email” scope for our sample.</p>

<p>I’ve extracted the ClientId and RedirectUrl from the PCL project, as it will differ from Android and iOS.</p>

<p>Here’s the result for my sample app:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">OAuth2Authenticator</span><span class="p">(</span>
    <span class="n">Configuration</span><span class="p">.</span><span class="n">ClientId</span><span class="p">,</span>
    <span class="kt">string</span><span class="p">.</span><span class="n">Empty</span><span class="p">,</span>
    <span class="s">"email"</span><span class="p">,</span>
    <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">"https://accounts.google.com/o/oauth2/v2/auth"</span><span class="p">),</span>
    <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">Configuration</span><span class="p">.</span><span class="n">RedirectUrl</span><span class="p">),</span>
    <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">"https://www.googleapis.com/oauth2/v4/token"</span><span class="p">),</span>
    <span class="n">isUsingNativeUI</span><span class="p">:</span> <span class="k">true</span><span class="p">);</span>
</code></pre></div></div>

<p>The OAuth2Authenticator class comes with two events: Completed and Error They’re quite simple to understand. The first one will call our handler when the authentication has completed (with the user authenticated or not) and the latter will allow us to react to an error (bad network, etc.)</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Auth</span><span class="p">.</span><span class="n">Completed</span> <span class="p">+=</span> <span class="n">OnAuthenticationCompleted</span><span class="p">;</span>
<span class="n">Auth</span><span class="p">.</span><span class="n">Error</span> <span class="p">+=</span> <span class="n">OnAuthenticationFailed</span><span class="p">;</span>
</code></pre></div></div>

<p>When the authentication ends, OnAuthenticationCompleted is called and we can check if the user is authenticated and retrieve the precious OAuth token that we need to call other APIs.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">private</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">AuthenticatorCompletedEventArgs</span> <span class="n">e</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">IsAuthenticated</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// The user is authenticated</span>
        <span class="c1">// Extract the OAuth token</span>
        <span class="kt">var</span> <span class="n">token</span> <span class="p">=</span> <span class="k">new</span> <span class="n">GoogleOAuthToken</span>
        <span class="p">{</span>
            <span class="n">TokenType</span> <span class="p">=</span> <span class="n">e</span><span class="p">.</span><span class="n">Account</span><span class="p">.</span><span class="n">Properties</span><span class="p">[</span><span class="s">"token_type"</span><span class="p">],</span>
            <span class="n">AccessToken</span> <span class="p">=</span> <span class="n">e</span><span class="p">.</span><span class="n">Account</span><span class="p">.</span><span class="n">Properties</span><span class="p">[</span><span class="s">"access_token"</span><span class="p">]</span>
        <span class="p">};</span>
        
        <span class="c1">// Do something</span>
    <span class="p">}</span>
    <span class="k">else</span>
    <span class="p">{</span>
        <span class="c1">// The user is not authenticated</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>N.B.: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Google/blob/master/Xamarin_GoogleAuth/Authentication/GoogleOAuthToken.cs">GoogleOAuthToken</a> is part of the sample.</p>

<p>While Xamarin.Auth usually doesn’t need anything else to work, Google authentication is a bit more tricky because it uses NativeUI. Xamarin.Auth will not be able to react to the redirection to RedirectUrl made by Google. For that, we will need to intercept the redirection ourselves (inside the Android and iOS projects) and provide the URL to Xamarin.Auth in order for it to ends the authentication flow. That requires us to keep the OAuth2Authenticator instance somewhere. I usually stores it as a static field, and clean it when I’m done.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="n">OAuth2Authenticator</span> <span class="n">Auth</span><span class="p">;</span>
</code></pre></div></div>

<p>That’s all for our Google implementation.</p>

<p>For a more detailed implementation, you can find the whole <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Google/blob/master/Xamarin_GoogleAuth/Authentication/GoogleAuthenticator.cs">GoogleAuthenticator file</a> used in the sample.</p>

<h4 id="3-retrieving-the-users-email-address">3. Retrieving the user’s email address</h4>

<p>We have done the hardest part. Things are quite simple once we have the OAuth token.</p>

<p>There’s a Google REST API that allows us to retrieve the user’s email address: https://www.googleapis.com/userinfo/email?alt=json</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="nf">GetEmailAsync</span><span class="p">(</span><span class="kt">string</span> <span class="n">tokenType</span><span class="p">,</span> <span class="kt">string</span> <span class="n">accessToken</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">httpClient</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpClient</span><span class="p">();</span>
    
    <span class="c1">// Provide the OAuth token as an Authorization header</span>
    <span class="n">httpClient</span><span class="p">.</span><span class="n">DefaultRequestHeaders</span><span class="p">.</span><span class="n">Authorization</span> <span class="p">=</span>
        <span class="k">new</span> <span class="nf">AuthenticationHeaderValue</span><span class="p">(</span><span class="n">tokenType</span><span class="p">,</span> <span class="n">accessToken</span><span class="p">);</span>
        
    <span class="c1">// Query the API</span>
    <span class="kt">var</span> <span class="n">json</span> <span class="p">=</span>
        <span class="k">await</span> <span class="n">httpClient</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span><span class="s">"https://www.googleapis.com/userinfo/email?alt=json"</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="n">DeserializeObject</span><span class="p">&lt;</span><span class="n">GoogleEmail</span><span class="p">&gt;(</span><span class="n">json</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">email</span><span class="p">.</span><span class="n">Data</span><span class="p">.</span><span class="n">Email</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>N.B.: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Google/blob/master/Xamarin_GoogleAuth/Services/GoogleEmail.cs">GoogleEmail</a> is also part of the sample.</p>

<p>And we’re done for the PCL part!</p>

<h3 id="implementing-google-authentication-in-the-android-project">Implementing Google authentication in the Android project</h3>

<h4 id="1-setting-the-package-name">1. Setting the package name</h4>

<p>First, make sure to set your package name properly. It needs to be the same as the one we declared for Android on the Google Developer Console. Here, I will set it to “com.woodenmoose.xamarin.googleauth”</p>

<p><em>AndroidManifest.xml</em></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="nt">&lt;manifest</span> <span class="err">(...)</span> <span class="na">package=</span><span class="s">"com.woodenmoose.xamarin.googleauth"</span><span class="nt">&gt;</span>
    (...)
<span class="nt">&lt;/manifest&gt;</span>
</code></pre></div></div>

<h4 id="2-installing-the-correct-nuget-packages">2. Installing the correct NuGet packages</h4>

<p>The Xamarin.Auth package is required by the Android project as well, as we need it to actually run an activity using CustomTabs. Fortunately the CustomTabs Support library is a required dependency and will be installed automatically.</p>

<p><strong><em>A bit of warning</em></strong><br />
If you continue and run the app now, you will end up with the following runtime exception:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>System.MissingMethodException: Method 'Android.Support.CustomTabs.CustomTabsIntent.LaunchUrl' not found.
</code></pre></div></div>

<p>That’s because Xamarin.Auth with IsUsingNativeUI will rely on CustomTabsIntent.LaunchUrl, which is only present in <a href="https://developer.android.com/reference/android/support/customtabs/CustomTabsIntent.html#launchUrl(android.content.Context, android.net.Uri)">v25 and beyond</a>.</p>

<p>You’ll need to make sure that you have installed at least the version v25.1.0. For that, just update the <a href="https://www.nuget.org/packages/Xamarin.Android.Support.CustomTabs/">Xamarin.Android.Support.CustomTabs package</a>. The sample uses the latest version which is v25.4.0.2. (CustomTabs v23 comes with Support.v4 library which is not required anymore with v25, you can remove it if you want)</p>

<h4 id="3-intercepting-the-redirection">3. Intercepting the redirection</h4>

<p>As I’ve said earlier, we need to intercept in place of Xamarin.Auth the redirection made by Google.</p>

<p>But first, we need to create that RedirectUrl. It can be anything you as long as it is a valid URL or respect the following scheme (protocol:/somedata). But as we don’t have control over the web browser, we need to make sure that Android warns us of the redirection.</p>

<p>For that, we will use deep linking. If our URL starts with our package name and the web browser tries to navigate to it, Android will launch our app, passing the URL as a parameter. The second part of the URL is just an identifier to differentiate other deep links that we may be using.</p>

<p>Here, our URL will be: “com.woodenmoose.xamarin.googleauth:/oauth2redirect”</p>

<p>Deep linking in Android requires an Activity with an IntentFilter.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nf">Activity</span><span class="p">(</span><span class="n">Label</span> <span class="p">=</span> <span class="s">"GoogleAuthInterceptor"</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">IntentFilter</span><span class="p">(</span><span class="n">actions</span><span class="p">:</span> <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">Intent</span><span class="p">.</span><span class="n">ActionView</span> <span class="p">},</span>
              <span class="n">Categories</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">Intent</span><span class="p">.</span><span class="n">CategoryDefault</span><span class="p">,</span> <span class="n">Intent</span><span class="p">.</span><span class="n">CategoryBrowsable</span> <span class="p">},</span>
              <span class="n">DataSchemes</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]</span>
              <span class="p">{</span>
                  <span class="c1">// First part of the redirect url (Package name)</span>
                  <span class="s">"com.woodenmoose.xamarin.googleauth"</span>
              <span class="p">},</span>
              <span class="n">DataPaths</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]</span>
              <span class="p">{</span>
                  <span class="c1">// Second part of the redirect url (Path)</span>
                  <span class="s">"/oauth2redirect"</span>
              <span class="p">})]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">GoogleAuthInterceptor</span> <span class="p">:</span> <span class="n">Activity</span>
<span class="p">{</span>
    <span class="p">(...)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When the redirection happens, Android will create a new instance of the GoogleAuthInterceptor activity. In the OnCreate method, we can get the URL and pass it to our OAuth2Authenticator. Make sure to finish the activity as we don’t need it anymore.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnCreate</span><span class="p">(</span><span class="n">Bundle</span> <span class="n">savedInstanceState</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">base</span><span class="p">.</span><span class="nf">OnCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">);</span>
    
    <span class="n">Android</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">Uri</span> <span class="n">uri_android</span> <span class="p">=</span> <span class="n">Intent</span><span class="p">.</span><span class="n">Data</span><span class="p">;</span>
    
    <span class="c1">// Convert Android Url to C#/netxf/BCL System.Uri</span>
    <span class="kt">var</span> <span class="n">uri_netfx</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">uri_android</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
    
    <span class="c1">// Send the URI to the Authenticator for continuation</span>
    <span class="n">MainActivity</span><span class="p">.</span><span class="n">Auth</span><span class="p">?.</span><span class="nf">OnPageLoading</span><span class="p">(</span><span class="n">uri_netfx</span><span class="p">);</span>
    
    <span class="nf">Finish</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="4-running-our-project">4. Running our project</h4>

<p>The last step is to run the actual authenticator. This will launch the native web browser and initiates the authentication.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// "this" is the current activity</span>
<span class="kt">var</span> <span class="n">intent</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
<span class="nf">StartActivity</span><span class="p">(</span><span class="n">intent</span><span class="p">);</span>
</code></pre></div></div>

<p>All that is left is to glue together all the pieces to make the Google authentication works on Android and retrieve the user’s email address</p>

<p><em>Configuration.cs</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">Configuration</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">ClientId</span> <span class="p">=</span> 
        <span class="s">"723962257721-ql0tki3si3s22l1lsovimivkmnrfm6rr.apps.googleusercontent.com"</span><span class="p">;</span>
        
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Scope</span> <span class="p">=</span> <span class="s">"email"</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">RedirectUrl</span> <span class="p">=</span>
        <span class="s">"com.woodenmoose.xamarin.googleauth:/oauth2redirect"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><em>MainActivity.cs</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nf">Activity</span><span class="p">(</span><span class="n">Label</span> <span class="p">=</span> <span class="s">"Xamarin_GoogleAuth"</span><span class="p">,</span> <span class="n">MainLauncher</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span> <span class="n">Icon</span> <span class="p">=</span> <span class="s">"@drawable/icon"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">Activity</span><span class="p">,</span> <span class="n">IGoogleAuthenticationDelegate</span>
<span class="p">{</span>
    <span class="c1">// Need to be static because we need to access it</span>
    <span class="c1">// in GoogleAuthInterceptor for continuation</span>
    <span class="k">public</span> <span class="k">static</span> <span class="n">GoogleAuthenticator</span> <span class="n">Auth</span><span class="p">;</span>
    
    <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnCreate</span><span class="p">(</span><span class="n">Bundle</span> <span class="n">bundle</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">OnCreate</span><span class="p">(</span><span class="n">bundle</span><span class="p">);</span>
        
        <span class="nf">SetContentView</span><span class="p">(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Layout</span><span class="p">.</span><span class="n">Main</span><span class="p">);</span>
        
        <span class="n">Auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GoogleAuthenticator</span><span class="p">(</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">ClientId</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">Scope</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">RedirectUrl</span><span class="p">,</span>
            <span class="k">this</span><span class="p">);</span> <span class="c1">// Completed/Error events</span>
            
        <span class="kt">var</span> <span class="n">googleLoginButton</span> <span class="p">=</span>
            <span class="n">FindViewById</span><span class="p">&lt;</span><span class="n">Button</span><span class="p">&gt;(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Id</span><span class="p">.</span><span class="n">googleLoginButton</span><span class="p">);</span>
            
        <span class="n">googleLoginButton</span><span class="p">.</span><span class="n">Click</span> <span class="p">+=</span> <span class="n">OnGoogleLoginButtonClicked</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">private</span> <span class="k">void</span> <span class="nf">OnGoogleLoginButtonClicked</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// Display the activity handling the authentication</span>
        <span class="kt">var</span> <span class="n">authenticator</span> <span class="p">=</span> <span class="n">Auth</span><span class="p">.</span><span class="nf">GetAuthenticator</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">intent</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
        <span class="nf">StartActivity</span><span class="p">(</span><span class="n">intent</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">async</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span><span class="n">GoogleOAuthToken</span> <span class="n">token</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// Retrieve the user's email address</span>
        <span class="kt">var</span> <span class="n">googleService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GoogleService</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span>
            <span class="k">await</span> <span class="n">googleService</span><span class="p">.</span><span class="nf">GetEmailAsync</span><span class="p">(</span>
                <span class="n">token</span><span class="p">.</span><span class="n">TokenType</span><span class="p">,</span>
                <span class="n">token</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
                
        <span class="c1">// Display it on the UI</span>
        <span class="kt">var</span> <span class="n">googleButton</span> <span class="p">=</span>
            <span class="n">FindViewById</span><span class="p">&lt;</span><span class="n">Button</span><span class="p">&gt;(</span><span class="n">Resource</span><span class="p">.</span><span class="n">Id</span><span class="p">.</span><span class="n">googleLoginButton</span><span class="p">);</span>
        
        <span class="n">googleButton</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="s">$"Connected with </span><span class="p">{</span><span class="n">email</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationFailed</span><span class="p">(</span><span class="kt">string</span> <span class="n">message</span><span class="p">,</span> <span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="n">AlertDialog</span><span class="p">.</span><span class="nf">Builder</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetTitle</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
            <span class="p">.</span><span class="nf">SetMessage</span><span class="p">(</span><span class="n">exception</span><span class="p">?.</span><span class="nf">ToString</span><span class="p">())</span>
            <span class="p">.</span><span class="nf">Show</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>N.B.: <a href="https://github.com/TimLariviere/Sample-XamarinAuth-Google/blob/master/Xamarin_GoogleAuth/Authentication/GoogleAuthenticator.cs">GoogleAuthenticator</a> is a PCL wrapper for OAuth2Authenticator that you can find in the sample.</p>

<p><img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/AndroidConnected.png" alt="" /></p>

<h3 id="implementing-google-authentication-in-the-ios-project">Implementing Google authentication in the iOS project</h3>

<h4 id="1-setting-the-package-name-1">1. Setting the package name</h4>

<p>First, make sure to set your package name properly. It needs to be the same as the one we declared for iOS on the Google Developer Console. Here, I will set it to “com.woodenmoose.xamarin.googleauth”</p>

<p><em>Info.plist</em></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;key&gt;</span>CFBundleIdentifier<span class="nt">&lt;/key&gt;</span>
<span class="nt">&lt;string&gt;</span>com.woodenmoose.xamarin.googleauth<span class="nt">&lt;/string&gt;</span>
</code></pre></div></div>

<h4 id="2-installing-nuget-packages">2. Installing NuGet packages</h4>

<p>Unlike Android, it can be done in a single step. Just install the Xamarin.Auth package in the iOS project.</p>

<h4 id="3-intercepting-the-redirection-1">3. Intercepting the redirection</h4>

<p>Just like Android, we will set up deep linking.</p>

<p>For that, we need to declare a URL type in the Info.plist file. We only have to declare our package name as a potential URL scheme that will launch our app.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;key&gt;</span>CFBundleURLTypes<span class="nt">&lt;/key&gt;</span>
<span class="nt">&lt;array&gt;</span>
    <span class="nt">&lt;dict&gt;</span>
        <span class="nt">&lt;key&gt;</span>CFBundleURLName<span class="nt">&lt;/key&gt;</span>
        <span class="nt">&lt;string&gt;</span>Google Auth<span class="nt">&lt;/string&gt;</span>
        <span class="nt">&lt;key&gt;</span>CFBundleURLSchemes<span class="nt">&lt;/key&gt;</span>
        <span class="nt">&lt;array&gt;</span>
            <span class="nt">&lt;string&gt;</span>com.woodenmoose.xamarin.googleauth<span class="nt">&lt;/string&gt;</span>
        <span class="nt">&lt;/array&gt;</span>
        <span class="nt">&lt;key&gt;</span>CFBundleURLTypes<span class="nt">&lt;/key&gt;</span>
        <span class="nt">&lt;string&gt;</span>Viewer<span class="nt">&lt;/string&gt;</span>
    <span class="nt">&lt;/dict&gt;</span>
<span class="nt">&lt;/array&gt;</span>
</code></pre></div></div>

<p>Or with the editor of Visual Studio: <a href="http://timothelariviere.com/wp-content/uploads/2017/08/07-iOSInfoPList.png"><img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/07-iOSInfoPList.png" alt="" /></a></p>

<p>Then every time Safari tries to navigate to a URL like “com.woodenmoose.xamarin.googleauth:/”, it will run our app and call the OpenUrl method of the AppDelegate class. Like we’ve done on Android, get the URL and pass it to our authenticator.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">OpenUrl</span><span class="p">(</span>
    <span class="n">UIApplication</span> <span class="n">application</span><span class="p">,</span> 
    <span class="n">NSUrl</span> <span class="n">url</span><span class="p">,</span> 
    <span class="kt">string</span> <span class="n">sourceApplication</span><span class="p">,</span> 
    <span class="n">NSObject</span> <span class="n">annotation</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// Convert iOS NSUrl to C#/netxf/BCL System.Uri</span>
    <span class="kt">var</span> <span class="n">uri_netfx</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">url</span><span class="p">.</span><span class="n">AbsoluteString</span><span class="p">);</span>
    <span class="n">AuthViewController</span><span class="p">.</span><span class="n">Auth</span><span class="p">?.</span><span class="nf">OnPageLoading</span><span class="p">(</span><span class="n">uri_netfx</span><span class="p">);</span>
    
    <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="4-running-our-project-1">4. Running our project</h4>

<p>The last step is to run the actual authenticator. This will launch the native web browser and initiates the authentication.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">viewController</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">();</span>
<span class="nf">PresentViewController</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
</code></pre></div></div>

<p>Also when you’re handling both Completed and Error events from the authenticator, you will need to manually call DismissViewController because the SFSafariViewController doesn’t dismiss itself.</p>

<p>And we glue everything together, this time for iOS!</p>

<p><em>Configuration.cs</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">Configuration</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">ClientId</span> <span class="p">=</span> 
        <span class="s">"723962257721-lcjvps5ag42butfd44tojo01cuj85d8t.apps.googleusercontent.com"</span><span class="p">;</span>
        
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Scope</span> <span class="p">=</span> <span class="s">"email"</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">RedirectUrl</span> <span class="p">=</span>
        <span class="s">"com.woodenmoose.xamarin.googleauth:/oauth2redirect"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><em>AuthViewController.cs</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">AuthViewController</span> <span class="p">:</span> <span class="n">UIViewController</span><span class="p">,</span> <span class="n">IGoogleAuthenticationDelegate</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="n">GoogleAuthenticator</span> <span class="n">Auth</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="nf">AuthViewController</span> <span class="p">(</span><span class="n">IntPtr</span> <span class="n">handle</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span> <span class="p">(</span><span class="n">handle</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span>
        
    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">ViewDidLoad</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">ViewDidLoad</span><span class="p">();</span>
        
        <span class="n">Auth</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GoogleAuthenticator</span><span class="p">(</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">ClientId</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">Scope</span><span class="p">,</span>
            <span class="n">Configuration</span><span class="p">.</span><span class="n">RedirectUrl</span><span class="p">,</span>
            <span class="k">this</span><span class="p">);</span> <span class="c1">// Completed/Error events</span>
            
        <span class="n">GoogleLoginButton</span><span class="p">.</span><span class="n">TouchUpInside</span> <span class="p">+=</span> <span class="n">OnGoogleLoginButtonClicked</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">private</span> <span class="k">void</span> <span class="nf">OnGoogleLoginButtonClicked</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">authenticator</span> <span class="p">=</span> <span class="n">Auth</span><span class="p">.</span><span class="nf">GetAuthenticator</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">viewController</span> <span class="p">=</span> <span class="n">authenticator</span><span class="p">.</span><span class="nf">GetUI</span><span class="p">();</span>
        <span class="nf">PresentViewController</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">async</span> <span class="k">void</span> <span class="nf">OnAuthenticationCompleted</span><span class="p">(</span>
        <span class="n">GoogleOAuthToken</span> <span class="n">token</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// SFSafariViewController doesn't dismiss itself</span>
        <span class="nf">DismissViewController</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
        
        <span class="kt">var</span> <span class="n">googleService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GoogleService</span><span class="p">();</span>
        <span class="kt">var</span> <span class="n">email</span> <span class="p">=</span>
            <span class="k">await</span> <span class="n">googleService</span><span class="p">.</span><span class="nf">GetEmailAsync</span><span class="p">(</span>
                <span class="n">token</span><span class="p">.</span><span class="n">TokenType</span><span class="p">,</span>
                <span class="n">token</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
                
        <span class="n">GoogleLoginButton</span><span class="p">.</span><span class="nf">SetTitle</span><span class="p">(</span><span class="s">$"Connected with </span><span class="p">{</span><span class="n">email</span><span class="p">}</span><span class="s">"</span><span class="p">,</span> <span class="n">UIControlState</span><span class="p">.</span><span class="n">Normal</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">void</span> <span class="nf">OnAuthenticationFailed</span><span class="p">(</span><span class="kt">string</span> <span class="n">message</span><span class="p">,</span> <span class="n">Exception</span> <span class="n">exception</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">// SFSafariViewController doesn't dismiss itself</span>
        <span class="nf">DismissViewController</span><span class="p">(</span><span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
        
        <span class="kt">var</span> <span class="n">alertController</span> <span class="p">=</span> <span class="k">new</span> <span class="n">UIAlertController</span>
        <span class="p">{</span> 
            <span class="n">Title</span> <span class="p">=</span> <span class="n">message</span><span class="p">,</span> 
            <span class="n">Message</span> <span class="p">=</span> <span class="n">exception</span><span class="p">?.</span><span class="nf">ToString</span><span class="p">()</span>
        <span class="p">};</span>
        
        <span class="nf">PresentViewController</span><span class="p">(</span><span class="n">alertController</span><span class="p">,</span> <span class="k">true</span><span class="p">,</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><img src="/assets/2017-09-01-authenticate-users-through-google-with-xamarin-auth/iOSConnected.png" alt="" /></p>

<p>And that concludes this really lengthy post. Hope it helps.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I’ve recently worked on a Xamarin app that needed to authenticate its users against Facebook, Google, and Twitter, and needed to retrieve their email addresses. Xamarin.Auth did the heavy lifting for us, handling all the OAuth authentication flow. But configuring it for Facebook, Google, and Twitter can be complicated as their configurations are (not so) slightly different.]]></summary></entry><entry><title type="html">One Mac. Small Xamarin team. How to. Part 2</title><link href="/2017/03/15/one-mac-small-xamarin-team-how-to-part-2/" rel="alternate" type="text/html" title="One Mac. Small Xamarin team. How to. Part 2" /><published>2017-03-15T00:00:00+00:00</published><updated>2017-03-15T00:00:00+00:00</updated><id>/2017/03/15/one-mac-small-xamarin-team-how-to-part-2</id><content type="html" xml:base="/2017/03/15/one-mac-small-xamarin-team-how-to-part-2/"><![CDATA[<p>Welcome in this long awaited part 2 of the serie “One Mac. Small Xamarin team. How to.”.</p>

<p>In part 1, we saw what possibilities in terms of hardware are available when developing for iOS with Xamarin (if you missed it, it’s still time to <a href="/2016/10/21/one-mac-small-xamarin-team-how-to-part-1/">read it</a>).</p>

<p>Today, I will explain how to leverage a single Mac for a small team, and how to enable simultaneous debugging between developers. This post is applicable to every Mac machines. A good candidate for such a setup would be either a Mac mini or a Mac Pro.</p>

<p>I won’t go into details about developer certificates and provisioning profiles.</p>

<p><strong>Contents:</strong></p>

<ul>
  <li><a href="#mac-side">The Mac Side</a>
    <ol>
      <li><a href="#mac-prerequisites">Prerequisites</a></li>
      <li><a href="#mac-create-accounts">Create the accounts</a></li>
      <li><a href="#mac-remote-access">Enable remote access</a></li>
    </ol>
  </li>
  <li><a href="#developer-side">The Developer Side</a>
    <ol>
      <li><a href="#developer-prerequisites">Prerequisites</a></li>
      <li><a href="#developer-remote-access">Remote access and configuring Xcode</a></li>
      <li><a href="#developer-visual-studio">Configuring Visual Studio</a></li>
      <li><a href="#developer-build-debug">Building, debugging, and simulating for iOS</a></li>
    </ol>
  </li>
  <li><a href="#limitations">Limitations</a></li>
  <li><a href="#conclusion">Conclusion</a></li>
</ul>

<h2 id="the-mac-side">The Mac Side</h2>

<h3 id="prerequisites">Prerequisites</h3>

<p>Before we start, make sure you have the following already set up.</p>

<ul>
  <li>A Mac, with the latest OS if possible. (at the time of writing: macOS Sierra)</li>
  <li>Xcode installed (at the time of writing: Xcode 8.2.1)</li>
  <li>Xamarin Studio/Visual Studio for Mac installed</li>
</ul>

<p>You won’t have to install all these softwares on each account as they will be globally available. And lastly, the Mac should be connected to your network and be reachable by any of your team mates.</p>

<h3 id="createthe-accounts">Create the accounts</h3>

<p>The first step to allow several developers to use the Mac simultaneously, to build and debug on both simulator and real devices, is to create each of them an account on the Mac. We can achieve that by manually creating those accounts or automate their creation by connecting the Mac to an Active Directory.</p>

<p>Both solutions take place in the “Users &amp; Groups” section of System Preferences.</p>

<p>If you’re manually creating the account, just add a standard account. Like this:</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/User.png" alt="" /></p>

<p>Repeat that step for each of your team mates and you’re done.</p>

<p>If you decide to let an Active Directory manage the accounts, you can join it in the “Login Options” tab. Click the “Join…” button of Network Account Server. To complete this step, you will need to have the login and password of one of the AD administrators.</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/JoinAD.png" alt="" /></p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/Capture.png" alt="" /></p>

<p>Note: macOS is currently not able to join an Azure Active Directory. If you’d like such feature, vote for it on <a href="https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/16117459-azure-ad-join-mac-os-x">feedback.azure.com</a>.</p>

<p>Make sure the “Allow network users to log in at login window” is ticked on. That way, anytime a new AD user connects to the Mac, his account will be automatically created.</p>

<h3 id="enable-remote-access">Enable remote access</h3>

<p>Now that we have created every accounts (or that we delegated their creation), we need to allow the users to connect to the Mac both through Visual Studio’s Xamarin Mac Agent and VNC.</p>

<p>The former requires us to activate the “Remote Login” service that allows for ssh access. To do that, we need to go to the “Sharing” section of System Preferences and tick on “Remote Login”. Make sure “Allow access for all users” is also ticked on (“Only these users” is also a valid option, as long as you add every of your team members’ accounts).</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/RemoteLogin.png" alt="" /></p>

<p>In order to allow developers to access the Mac and configure their Xcode with an Apple Developer account so that they can download provisioning profile, we need to put a remote desktop service in place. OS X has a really great feature for this: it can natively be a VNC server without anything to install.</p>

<p>We can activate this feature by going in the “Sharing” section of System Preferences. There, just turn on the “Screen Sharing” service and allow access for all users (again use “Only these users” if you want).</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/ScreenSharing.png" alt="" /></p>

<p>Now whenever someone wants to access the Mac through a VNC client, he will be asked of his credentials. When done, he will access his own account.</p>

<p>OS X is capable of handling several sessions running simultaneously when using VNC, so each developer can use it independently.</p>

<p>And that’s all for the global configuration part! Now we’ll see how each developer needs to configure his Mac account and Visual Studio so that he can build and debug iOS apps directly from Visual Studio.</p>

<p> </p>

<h2 id="the-developer-side">The Developer Side</h2>

<h3 id="prerequisites-1">Prerequisites</h3>

<p>I will only talk about Visual Studio on Windows. So here’s the prerequisites :</p>

<ul>
  <li>Visual Studio 2015/2017 installed</li>
  <li>Xamarin for Visual Studio installed</li>
  <li>VNC client (like <a href="https://www.realvnc.com/download/viewer/">RealVNC</a>)</li>
</ul>

<p>The computer needs to have access to the same network as the Mac, and be able to communicate with it.</p>

<h3 id="remote-access-and-configuring-xcode">Remote access and configuring Xcode</h3>

<p>Before doing anything, we should connect to the Mac via VNC. The important part here is to use your own account to access it so that it will open your own session.</p>

<p>If you have set up an Active Directory, it will be at the time of the first connection that the account will be created.</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/Login-1024x594.png" alt="" /></p>

<p>Now is a good time to configure Xcode to use your Apple developer account and download any provisioning profile that you will need. The Xamarin.iOS compiler (and by extension Visual Studio) will rely on those configurations to actually build your app.</p>

<p>You’re also free to do whatever you want on the Mac. You could, for example, install git and clone your repository. That way, you could make your storyboards directly on the Xcode designer!</p>

<p>Remember, you’re on your own session with its own home directory!</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/Account-1024x594.png" alt="" /></p>

<p>A warning though: VNC can be quite sluggish so it can be a little frustrating to work through remote access.</p>

<h3 id="configuring-visual-studio">Configuring Visual Studio</h3>

<p>Lastly, we need to configure Visual Studio. This part is simple. Xamarin also helps you with a tutorial right inside Visual Studio.</p>

<p>With a Xamarin.iOS project loaded, you will be able to access the Xamarin Remote Agent icon.</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/XamarinMacAgent.png" alt="" /></p>

<p>Click on it and just search for the Mac, either by its name or by its IP address.</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/Connect.png" alt="" /></p>

<p>To connect, Visual Studio will ask for the credentials to use. It’s important to give your own credentials! That way, it will connect to your session to build and debug. It’s the key to allow several developers to debug at the same time.</p>

<p><img src="/assets/2017-03-14-one-mac-small-xamarin-team-how-to-part-2/Debug.png" alt="" /></p>

<p>Visual Studio will be able to connect only if your session is currently running, so remember to log in through VNC beforehand. Otherwise you will end up with the following console output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Starting connection to Mac mcnmac002.local....
The user must be logged in on the Mac in order to execute an SSH command.
Disconnected from the Mac mcnmac002.local.
</code></pre></div></div>

<p>This will be true every time you start Visual Studio and try to build/debug a Xamarin.iOS app.</p>

<h3 id="building-debugging-and-simulating-for-ios">Building, debugging and simulating for iOS</h3>

<p>And that’s it for the Developer side! You can now build, debug, and use the simulator simultaneously on a single Mac.</p>

<p>If you want to deploy on a real device, you will still need to plug it into one of the Mac’s USB ports. Xamarin has announced some time ago an iOS USB Remoting feature, but as of the time of writing, we’re still waiting for it.</p>

<p>Make sure to try out the Remote iOS Simulator for Visual Studio! It will be a little easier to use than the iOS Simulator on the Mac through VNC.</p>

<h2 id="limitations">Limitations</h2>

<p>There’s some drawbacks when using this setup.</p>

<ul>
  <li>You will need a slightly more powerful machine, compared to when you have your own Mac, as it will need to handle remote access and simultaneous build/debug/simulators.</li>
  <li>Disk space will quickly vanish due to how Xamarin Studio works (huge caches per user, Android SDK installed once per user by default).</li>
  <li>Remote builds are noticeably longer than direct builds</li>
  <li>The Visual Studio’s Mac Remote Agent needs a running session on the Mac, and it can be quite erratic (this was especially true some months back on VS2015)</li>
  <li>Remote access with VNC is not optimal.
    <ul>
      <li>There could be some delay for the screen to refresh.</li>
      <li>Even worse, if there’s no screen plugged in the Mac, VNC will only stream a resolution of 640x480. Huge black rectangles will appear on the screen making it near unusable. I recently bought a small HDMI plug that emulates the presence of a screen (you can find it here on <a href="https://www.amazon.com/CompuLab-fit-Headless-Display-Emulator/dp/B00FLZXGJ6">Amazon</a>) and it solved those issues (1080p stream, no black rectangle).</li>
    </ul>
  </li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>Despite the length of this post, we saw that configuring a Mac to allow several developers to work it simultaneously is quite simple and straightforward. It even works remarkably well!</p>

<p>It can be a good solution if you’re low on budget or the number of iOS projects don’t justify the cost of buying every single developer a Mac. But if you can, prefer to equip everyone of your team mates with a MacBook Pro or equivalent. It will spare you a lot of misadventures.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Welcome in this long awaited part 2 of the serie “One Mac. Small Xamarin team. How to.”.]]></summary></entry><entry><title type="html">Call an Azure AD protected API in Xamarin/UWP apps</title><link href="/2017/02/13/call-an-azure-ad-protected-api-in-xamarinuwp-apps/" rel="alternate" type="text/html" title="Call an Azure AD protected API in Xamarin/UWP apps" /><published>2017-02-13T00:00:00+00:00</published><updated>2017-02-13T00:00:00+00:00</updated><id>/2017/02/13/call-an-azure-ad-protected-api-in-xamarinuwp-apps</id><content type="html" xml:base="/2017/02/13/call-an-azure-ad-protected-api-in-xamarinuwp-apps/"><![CDATA[<p>When we talk about mobile apps, a web API is generally hiding in the background, doing most of the work like connecting to a database, verifying authorization, computing data, and so on. Like everything else, those APIs need protection against unauthorized calls that don’t come from our mobile apps.</p>

<p>In this post, I will explain how to leverage Azure Active Directory to protect our WebAPI without any code, and how to call this WebAPI from our mobile apps.</p>

<h3 id="so-how-do-we-do-that">So, how do we do that?</h3>

<p>In order, we will :</p>

<ol>
  <li>Enable Azure AD authentication on our API</li>
  <li>Declare our apps in the Azure AD in order to allow them to authenticate their users and give them access to our API</li>
  <li>Implement ADAL.NET in our apps to authenticate the user and retrieve an access token for our API</li>
  <li>Call our API with the access token</li>
  <li>???</li>
  <li>Profit</li>
</ol>

<h3 id="before-we-begin">Before we begin</h3>

<p>For this post, I will use the default ASP.NET Core WebAPI that I will host in an Azure App Service. The mobile apps will be made with Xamarin.iOS, Xamarin.Android and UWP, core logic will be implemented inside a .NETStandard 1.4 project.</p>

<p>I made a sample containing the WebAPI and the mobile apps, it’s available on Github : <a href="https://github.com/TimLariviere/WoodenMoose.Samples.Xamarin_Authentication">https://github.com/TimLariviere/WoodenMoose.Samples.Xamarin_Authentication</a></p>

<p>If you want to run the sample, you will need to have an active Azure subscription with an Azure Active Directory. Then you will need to declare your apps in the Azure AD like we will see in this post.</p>

<h3 id="configuring-azure-ad-for-the-webapi">Configuring Azure AD for the WebAPI</h3>

<p>Before we can do anything with Xamarin or UWP, we need to set up our WebAPI and configure the authentication against Azure Active Directory. This used to require lots of setup code in our WebAPI in order to allow only authenticated requests, most of the times specific to only one identity provider. Well, this time Azure really make it easy on us with a “turn key” feature that require no code at all!</p>

<p>I have already created an Azure App Service named “<strong>woodenmoose-authsample-api</strong>” and published in it an ASP.NET Core WebAPI, generated from the default template.</p>

<p>To enable authentication with Azure AD, I just need to go into the “Authentication / Authorization” panel, turn the feature on and configure it to create a new Azure AD app representing my WebAPI. Like this : <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/Authentication-1024x532.png" alt="Authentication" /></p>

<p>That’s it! As promised, we protected the WebAPI with no code whatsoever, as you can see when asking for the <strong>Index</strong> action of the <strong>ValuesController</strong>. <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/Capture6-1024x641.png" alt="Capture6" /></p>

<h3 id="configuring-azure-ad-for-the-mobile-apps">Configuring Azure AD for the mobile apps</h3>

<p>Our API is now protected by Azure AD and we can authenticate ourselves directly in the browser, but our mobile apps aren’t ready yet to query the API. This is because Azure AD won’t issue access tokens to unknown clients.</p>

<p>So there’s a little more configuration to do.</p>

<p>First, we’ll create a new <strong>native</strong> app entry into the Azure AD apps registry. I have named it “<strong>woodenmoose-authsample-mobileapp</strong>”.</p>

<p>The RedirectUri will be used in the mobile apps to notify the success of the authentication. It can be any URI that you want. But if you’re going for multitenancy authentication, Azure requires you follow a specific pattern : https://yourtenantname.com/what_you_want</p>

<p>I have set the value to “<strong>https://mcnext.com/woodenmoose-authsample-mobileapp</strong>”</p>

<p><img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/Capture5.png" alt="Capture5" /></p>

<p>Next, we’ll need to allow users connected to woodenmoose-authsample-mobileapp to access the web API. For this, we have the “Required permissions” panel in the native app entry. In it, we will select the api entry from the Azure AD.</p>

<p>Like this : <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/DelegatedPermissions-1024x507.png" alt="DelegatedPermissions" /></p>

<p>And then, we set the permission needed. In our case, simply “<strong>Access woodenmoose-authsample-api</strong>”. <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps//Capture4-1024x225.png" alt="Capture4" /></p>

<p>And finally, the last step in configuring Azure AD is to tell our api registration that if our native app registration want to issue a token to access the API, it’s ok.</p>

<p>So we have to change our api registration and fill the “knownClientApplications” array in the manifest with the ApplicationId of our native app registration.</p>

<p>We have to use the manifest, because there’s no other interface that will allow us to do so. <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/Capture2-1024x495.png" alt="Capture2" /></p>

<p>And that’s it for the configuration! You’re still there? Great, because now we’re finally going to write some code!</p>

<h3 id="implementing-adalnet">Implementing ADAL.NET</h3>

<p>Now that all the configuration part on Azure is done, we can implement the authentication process in our apps before we can make a call to our API. For that, we will use <a href="https://github.com/AzureAD/azure-activedirectory-library-for-dotnet">ADAL.NET</a> (standing for Active Directory Authentication Library for dotNET) which is compatible with our 3 platforms.</p>

<p>ADAL.NET will take care of everything. It will display a screen where the user will log in, handle every error cases (wrong account, wrong password, account disabled, etc.) and it will handle the OAuth process. At the end, you receive the access token that you need to query the API. Really simple!</p>

<p>So, to use ADAL.NET we need to add to our core library the nuget package “<a href="https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/">Microsoft.IdentityModel.Clients.ActiveDirectory</a>” (version 3.13.8 at the time of writing)</p>

<p>A few tips so NuGet will accept to install ADAL :</p>

<ul>
  <li>If you’re making a PCL project, you’ll need to target the PCL Profile 7 (see image below for which platforms to select)</li>
  <li>If you’re making a .NETStandard project, you’ll need to target at least .NET Standard 1.4</li>
</ul>

<p>The reason is that the ADAL package is only compatible with those versions.</p>

<p>Here are the required platforms if you’re making a PCL. <img src="/assets/2017-02-12-call-an-azure-ad-protected-api-in-xamarinuwp-apps/pcl-targets.png" alt="pcl-targets" /></p>

<p>Once ADAL installed, we have access to the <strong>AuthenticationContext</strong> class. With it, we can ask for the user to log in.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">AuthenticationManager</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="kt">string</span> <span class="n">_authority</span><span class="p">;</span>
    <span class="k">private</span> <span class="kt">string</span> <span class="n">_resource</span><span class="p">;</span>
    <span class="k">private</span> <span class="kt">string</span> <span class="n">_clientId</span><span class="p">;</span>
    <span class="k">private</span> <span class="n">Uri</span> <span class="n">_redirectUri</span><span class="p">;</span>
    <span class="k">private</span> <span class="k">static</span> <span class="n">IPlatformParameters</span> <span class="n">_platformParameters</span><span class="p">;</span>
    <span class="k">private</span> <span class="kt">string</span> <span class="n">_accessToken</span><span class="p">;</span>
    
    <span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">LoginAsync</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">authContext</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">AuthenticationContext</span><span class="p">(</span><span class="n">_authority</span><span class="p">);</span>
        <span class="kt">var</span> <span class="n">authResult</span> <span class="p">=</span>
            <span class="k">await</span> <span class="n">authContext</span><span class="p">.</span><span class="nf">AcquireTokenAsync</span><span class="p">(</span>
                <span class="n">_resource</span><span class="p">,</span> <span class="n">_clientId</span><span class="p">,</span> <span class="n">_redirectUri</span><span class="p">,</span> <span class="n">_platformParameters</span><span class="p">);</span>
                
        <span class="kt">var</span> <span class="n">connectedUser</span> <span class="p">=</span> <span class="n">authResult</span><span class="p">.</span><span class="n">UserInfo</span><span class="p">;</span>
        <span class="n">_accessToken</span> <span class="p">=</span> <span class="n">authResult</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">SetParameters</span><span class="p">(</span><span class="n">IPlatformParameters</span> <span class="n">platformParameters</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">_platformParameters</span> <span class="p">=</span> <span class="n">platformParameters</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Our LoginAsync method needs some parameters, let me explain them :</p>

<table>
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Description</th>
      <th>Where to get it</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Authority</td>
      <td>URL of the authentication authority</td>
      <td>Two values are possible<br />- If multitenancy is activated : <strong>https://login.windows.net/common/</strong><br />- Otherwise : <strong>https://login.windows.net/yourtenantname.com/</strong></td>
    </tr>
    <tr>
      <td>Resource*</td>
      <td>Guid associated to the web app registration that we want to get a token for.</td>
      <td>This value can be found in the properties of the web app registration under the name “Application ID” (Thanks Darren for correcting that)</td>
    </tr>
    <tr>
      <td>ClientId</td>
      <td>Guid associated to the native app registration that we want to authenticate against</td>
      <td>This value can be found in the properties of the native app registration under the name “Application ID”</td>
    </tr>
    <tr>
      <td>RedirectUri</td>
      <td>URI that the OAuth process will call if the authentication is successful</td>
      <td>This value is the one that we configured in the native app registration. It can be found in the “Redirect URIs” panel.</td>
    </tr>
    <tr>
      <td>PlatformParameters</td>
      <td>Platform specific interface that will change how ADAL.NET works</td>
      <td>We need to pass an instance of a platform specific implementation of this interface. We will see how in the next parts</td>
    </tr>
  </tbody>
</table>

<p><em>For the Resource parameter, it seems that some Azure AD will accept that you give an URI (App ID) instead of a Guid. But I recommend that you give the Guid anyway so there won’t be any surprises.</em></p>

<p>So for my case, I’ll use those values</p>

<ul>
  <li>Authority = <strong>https://login.windows.net/mcnext.com/</strong></li>
  <li>Resource = <strong>c21a38b2-54bb-4027-b5e4-257f7d10f3f9</strong></li>
  <li>ClientId = <strong>150526ad-75ee-44d5-a6e1-091ef0900d77</strong></li>
  <li>RedirectUri = <strong>https://mcnext.com/woodenmoose-authsample-mobileapp</strong></li>
</ul>

<p>We are still missing the PlatformParameters instance for ADAL.NET to work. Instanciating PlatformParameters is different for each platform so we will see how to do so for iOS, Android, and UWP.</p>

<h4 id="implementing-ios">Implementing iOS</h4>

<p>The first step (after adding a reference to our core project) is to add a reference to the NuGet package “<a href="https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/">Microsoft.IdentityModel.Clients.ActiveDirectory</a>” like in our core projet. The reason is that this package will come with a platform specific DLL (for instance Microsoft.IdentityModel.Clients.ActiveDirectory.Platform) which contains the iOS implementation of the IPlatformParameters interface.</p>

<p>Then all that remains is to give our core project an instance of the iOS PlatformParameters</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">MainViewController</span> <span class="p">:</span> <span class="n">UIViewController</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">ViewDidLoad</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">platformParameters</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">PlatformParameters</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
        <span class="n">AuthenticationManager</span><span class="p">.</span><span class="nf">SetParameters</span><span class="p">(</span><span class="n">platformParameters</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>ADAL.NET requires that you give it the instance of the currently displayed UIViewController, so it can resume our application once the authentication is complete. And we’re done for iOS.</p>

<h4 id="implementing-android">Implementing Android</h4>

<p>Android is mostly the same as iOS, to a slight exception. We need to reference the NuGet package “<a href="https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/">Microsoft.IdentityModel.Clients.ActiveDirectory</a>”.</p>

<p>And we need to pass our Android implementation of PlatformParameters the instance of our currently displayed Activity.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">MainActivity</span> <span class="p">:</span> <span class="n">Activity</span>
<span class="p">{</span>
    <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnCreate</span><span class="p">(</span><span class="n">Bundle</span> <span class="n">bundle</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">platformParameters</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">PlatformParameters</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
        <span class="n">AuthenticationManager</span><span class="p">.</span><span class="nf">SetParameters</span><span class="p">(</span><span class="n">platformParameters</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnActivityResult</span><span class="p">(</span>
        <span class="kt">int</span> <span class="n">requestCode</span><span class="p">,</span> <span class="n">Result</span> <span class="n">resultCode</span><span class="p">,</span> <span class="n">Intent</span> <span class="n">data</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">OnActivityResult</span><span class="p">(</span><span class="n">requestCode</span><span class="p">,</span> <span class="n">resultCode</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
        
        <span class="n">AuthenticationAgentContinuationHelper</span>
            <span class="p">.</span><span class="nf">SetAuthenticationAgentContinuationEventArgs</span><span class="p">(</span><span class="n">requestCode</span><span class="p">,</span> <span class="n">resultCode</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Notice that I have overridden the OnActivityResult method. AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs needs to be called on OnActivityResult, otherwise ADAL.NET will not be able to resume our application on authentication success.</p>

<h4 id="implementing-uwp">Implementing UWP</h4>

<p>Like iOS and Android, UWP needs to reference the NuGet Package “<a href="https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/">Microsoft.IdentityModel.Clients.ActiveDirectory</a>”. If you try to build now, you may notice that the build fails. Just update your “Microsoft.NETCore.UniversalWindowsPlatform” package to version 5.2.2 minimum.</p>

<p>Unlike iOS and Android, UWP doesn’t need to access the currently displayed Window. So instead, we can just set up our PlatformParameters in the App.xaml.cs file.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">partial</span> <span class="k">class</span> <span class="nc">App</span> <span class="p">:</span> <span class="n">Application</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="nf">App</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nf">InitializeComponent</span><span class="p">();</span>
        <span class="k">this</span><span class="p">.</span><span class="n">Suspending</span> <span class="p">+=</span> <span class="n">OnSuspending</span><span class="p">;</span>
        
        <span class="kt">var</span> <span class="n">platformParameters</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">PlatformParameters</span><span class="p">(</span><span class="n">PromptBehavior</span><span class="p">.</span><span class="n">Auto</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
        <span class="n">AuthenticationManager</span><span class="p">.</span><span class="nf">SetParameters</span><span class="p">(</span><span class="n">platformParameters</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="what-about-xamarinforms">What about Xamarin.Forms?</h4>

<p>Well, it works the same way as we saw for iOS, Android, and UWP. The only thing that differ is how to retrieve the current UIViewController and Activity. See the blog post from Xamarin “<a href="https://blog.xamarin.com/put-adal-xamarin-forms/">Put Some Azure Active Directory in Xamarin.Forms</a>” for more information.</p>

<h3 id="calling-the-api">Calling the API</h3>

<p>Now that we finally have the access token, we can use it with HttpClient. To use it, we just have to set the Authorization header.</p>

<p>Like this:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">HttpClient</span><span class="p">();</span>
<span class="n">client</span><span class="p">.</span><span class="n">DefaultRequestHeaders</span><span class="p">.</span><span class="n">Authorization</span> <span class="p">=</span>
    <span class="k">new</span> <span class="nf">AuthenticationHeaderValue</span><span class="p">(</span><span class="s">"Bearer"</span><span class="p">,</span> <span class="n">_accessToken</span><span class="p">);</span>

<span class="kt">var</span> <span class="n">result</span> <span class="p">=</span>
    <span class="k">await</span> <span class="n">client</span><span class="p">.</span><span class="nf">GetAsync</span><span class="p">(</span><span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">"https://woodenmoose-authsample-api.azurewebsites.net/api/values"</span><span class="p">));</span>
</code></pre></div></div>

<p>That way, Azure AD will allow our request to be answered by our WebAPI.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Setting up authentication and authorization can be quite a challenge, but ADAL and Azure Active Directory simplified it for us, especially since we’re targeting 3 different platforms. Of course, we only saw the bare minimum. ADAL.NET has plenty more features to help you deliver secured and easy to use apps like token cache, refresh session, and so on. See the ADAL.NET GitHub for more information : <a href="https://github.com/AzureAD/azure-activedirectory-library-for-dotnet">https://github.com/AzureAD/azure-activedirectory-library-for-dotnet</a></p>

<p>Also I have made a sample on Github demonstrating everything I showed in this post : <a href="https://github.com/TimLariviere/WoodenMoose.Samples.Xamarin_Authentication">https://github.com/TimLariviere/WoodenMoose.Samples.Xamarin_Authentication</a></p>

<p>Happy coding!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[When we talk about mobile apps, a web API is generally hiding in the background, doing most of the work like connecting to a database, verifying authorization, computing data, and so on. Like everything else, those APIs need protection against unauthorized calls that don’t come from our mobile apps.]]></summary></entry><entry><title type="html">.NET Core – Hide file / folder from project in Visual Studio 2015</title><link href="/2017/01/18/net-core-hide-file-folder-from-project-in-visual-studio-2015/" rel="alternate" type="text/html" title=".NET Core – Hide file / folder from project in Visual Studio 2015" /><published>2017-01-18T00:00:00+00:00</published><updated>2017-01-18T00:00:00+00:00</updated><id>/2017/01/18/net-core-hide-file-folder-from-project-in-visual-studio-2015</id><content type="html" xml:base="/2017/01/18/net-core-hide-file-folder-from-project-in-visual-studio-2015/"><![CDATA[<p>A few warnings before we begin :</p>

<ul>
  <li>This post is only about Visual Studio 2015. In Visual Studio 2017, you can find the option “Hide from Solution Explorer” in the context menu.</li>
  <li>Also this post is only about xproj-based projects. It applies to .NET Core libs and apps like ASP.NET Core. The next version of .NET Core (2.0) will revert back to csproj files.</li>
</ul>

<p>Unlike csproj-based projects where files need to be referenced in the csproj, with xproj-based projects Visual Studio will list by default every files in the project folder in the Solution Explorer.</p>

<p>To avoid cluttering your Solution Explorer with unneeded files, you will need to edit the xproj file to add files or folders to exclude.</p>

<p>Here the available options :</p>

<table>
  <thead>
    <tr>
      <th>Tag</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>DnxInvisibleContent</td>
      <td>Hide a single file</td>
    </tr>
    <tr>
      <td>DnxInvisibleFolder</td>
      <td>Hide a single folder</td>
    </tr>
  </tbody>
</table>

<p>A limitation with these tags is that there no pattern available. It needs to be a specific file or folder name.</p>

<p>These tags needs to be written inside an <em><strong>ItemGroup</strong></em> tag which in turn need to be put inside the <em><strong>Project</strong></em> root of the xproj file. Like this :</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="nt">&lt;Project</span> <span class="na">ToolsVersion=</span><span class="s">"14.0"</span> <span class="na">DefaultTargets=</span><span class="s">"Build"</span> <span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/developer/msbuild/2003"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;ItemGroup&gt;</span>
        <span class="nt">&lt;DnxInvisibleContent</span> <span class="na">Include=</span><span class="s">"nuget.exe"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;DnxInvisibleFolder</span> <span class="na">Include=</span><span class="s">"node\_modules"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/ItemGroup&gt;</span>
<span class="nt">&lt;/Project&gt;</span>
</code></pre></div></div>]]></content><author><name></name></author><summary type="html"><![CDATA[A few warnings before we begin :]]></summary></entry></feed>