<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mike James</title>
    <description>The latest articles on DEV Community by Mike James (@mikecodesdotnet).</description>
    <link>https://dev.to/mikecodesdotnet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F193119%2Fef3655e4-3f00-462d-8ca7-97aab8a9abb0.png</url>
      <title>DEV Community: Mike James</title>
      <link>https://dev.to/mikecodesdotnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mikecodesdotnet"/>
    <language>en</language>
    <item>
      <title>WPF App Modernisation: A Pragmatic Approach</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Fri, 13 Oct 2023 08:37:55 +0000</pubDate>
      <link>https://dev.to/avalonia/wpf-app-modernisation-a-pragmatic-approach-4bcd</link>
      <guid>https://dev.to/avalonia/wpf-app-modernisation-a-pragmatic-approach-4bcd</guid>
      <description>&lt;p&gt;In the world of desktop application development, continuity and stability often trump the allure of new frameworks. Notably, 58% of professional desktop developers stick with the familiar, avoiding radical  changes to their applications. The predominant drive is maintaining or modernising applications within the familiar confines of their existing UI technologies. This preference is not without merit; developers find comfort in the known, and a lower developmental cost comes with familiarity. Rewriting an application is a significant financial and operational risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Platform UI Toolkits
&lt;/h2&gt;

&lt;p&gt;That's not to say some teams aren't seriously considering their modernisation strategy. While WPF is stable and proven, it is limited to Windows at a time when more and more applications need to run on various operating systems and form factors. Before &lt;a href="https://avaloniaui.net/XPF" rel="noopener noreferrer"&gt;Avalonia XPF&lt;/a&gt;, WPF developers had limited options. One option would be to migrate to a cross-platform UI toolkit, such as &lt;a href="https://avaloniaui.net/" rel="noopener noreferrer"&gt;Avalonia&lt;/a&gt;, &lt;a href="https://www.qt.io/" rel="noopener noreferrer"&gt;Qt&lt;/a&gt; or &lt;a href="https://flutter.dev/" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt;, with the best-case scenario enabling some code reuse and the worst case requiring a complete application rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web
&lt;/h2&gt;

&lt;p&gt;The alternative to a cross-platform UI toolkit has been embracing Web technologies, whether &lt;a href="https://www.electronjs.org/" rel="noopener noreferrer"&gt;Electron&lt;/a&gt; or moving to the cloud. It's hard to ignore the allure of web technology's ease of deployment, albeit at the potential expense of performance and productivity. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why modernise
&lt;/h2&gt;

&lt;p&gt;With so many mission-critical WPF applications in active development, the discussion of modernisation is buzzing. Why the discourse on modernisation, you ask? The answer is twofold: new platforms equate to an expanded target market and a resilient, future-proof application portfolio. The pathway to modernisation, however, is a strategic decision. Rewriting is an expensive endeavour, irrespective of the technology chosen. The crossroads broadly split into native cross-platform (embodied by Flutter, QT, Avalonia, etc...) or the web. Amongst the native cross-platform contenders,  Avalonia emerges as the frontrunner in facilitating code reuse, a significant cost and time efficiency advantage. That isn't to say that Avalonia (our open-source, cross-platform UI toolkit) doesn't require some changes to your WPF app. It's WPF-inspired but not binary-compatible. &lt;/p&gt;

&lt;h2&gt;
  
  
  Avalonia XPF
&lt;/h2&gt;

&lt;p&gt;If you need WPF binary compatibility, then &lt;a href="https://avaloniaui.net/XPF" rel="noopener noreferrer"&gt;Avalonia XPF&lt;/a&gt; has emerged as a solution to modernisation. It offers a path to new platforms without necessitating a seismic shift and rewriting existing applications. We typically see customers running their complex WPF application on new platforms within only a few hours of receiving a trial license! The attraction towards Avalonia XPF stems from a pragmatic standpoint; it's a fast and affordable conduit to broader market reach without the enormous risk of rewriting applications from scratch in a different technology. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://avaloniaui.net/XPF" rel="noopener noreferrer"&gt;Avalonia XPF&lt;/a&gt; shines distinctly, enabling full reuse of existing WPF code and 3rd party controls while providing performance improvements and new platforms. It's a proposition of extending the life and reach of your applications without a daunting overhaul.&lt;/p&gt;

&lt;p&gt;There isn't a one-size-fits-all answer to app modernisation. It's a journey tailored to individual applications and a team's long-term vision. Engaging in a dialogue on modernisation, understanding the nuances and making informed decisions is the essence of staying ahead. We at Avalonia are at the helm to discuss, advise, and help you navigate the modernisation maze. &lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;If you'd like to test your WPF applications on macOS or Linux, then &lt;a href="https://avaloniaui.net/XPF/Interest" rel="noopener noreferrer"&gt;sign up for a 30-day trial of Avalonia XPF&lt;/a&gt;. &lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Remember to download our XPF Sample app, &lt;a href="https://avaloniaui.net/FamilyShow" rel="noopener noreferrer"&gt;FamilyShow&lt;/a&gt;. The classic WPF sample app is now available on macOS and Linux! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvh555ee580zt4zrcvc7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvh555ee580zt4zrcvc7q.png" alt="FamilyShow App on macOS"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wpf</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>xaml</category>
    </item>
    <item>
      <title>Introducing Avalonia XPF Trials and the Startup License</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Thu, 27 Jul 2023 11:00:09 +0000</pubDate>
      <link>https://dev.to/avalonia/introducing-avalonia-xpf-trials-and-the-startup-license-1em4</link>
      <guid>https://dev.to/avalonia/introducing-avalonia-xpf-trials-and-the-startup-license-1em4</guid>
      <description>&lt;p&gt;At Avalonia, we embarked on the ambition project of Avalonia XPF with the aim of extending the reach of Windows Presentation Foundation (WPF) to a broader range of platforms. Today, as we witness numerous companies finding success with Avalonia XPF, we are proud of the progress we’ve made. The fruits of our labor are visible, and we’re thrilled to announce that we’re being XPF Trials and added a license specifically targeting small businesses. &lt;/p&gt;

&lt;h2&gt;
  
  
  Avalonia XPF Trials
&lt;/h2&gt;

&lt;p&gt;After rigorous testing and refinement over many months with a select group of companies, we are now ready to extend Avalonia XPF trials to the broader community. Avalonia XPF has seen exponential improvements since the start of the year. We are now proudly supporting a significant proportion of major WPF control vendors. Collaborations with esteemed vendors like &lt;a href="https://www.actiprosoftware.com/" rel="noopener noreferrer"&gt;Actipro&lt;/a&gt; and &lt;a href="https://www.scichart.com/" rel="noopener noreferrer"&gt;SciChart&lt;/a&gt; are enabling us to ensure that controls function seamlessly across all supported platforms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegf6b9f7sn5jlt18ke9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegf6b9f7sn5jlt18ke9o.png" alt="Avalonia XPF running a Infragistics WPF sample on Linux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This exciting expansion of our testing phase is organized into four straightforward steps to ensure a seamless onboarding experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;br&gt;
Users interested in exploring the potential of Avalonia XPF can &lt;a href="https://avaloniaui.net/xpf/interest" rel="noopener noreferrer"&gt;apply for a trial&lt;/a&gt; through our website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; &lt;br&gt;
Our team will set up a short initial call to verify the compatibility of the user's app, discuss timelines, and understand specific requirements. This step allows us to personalize your trial experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt;&lt;br&gt;
Once we've established the app’s suitability and your readiness, we help set you up with the Avalonia XPF trial. Our dedicated team is on standby to assist should any issues arise while using Avalonia XPF.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; &lt;br&gt;
After a successful trial, users can purchase a license to officially bring their WPF application to macOS and Linux, opening up their products to a significantly wider user base.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylyay41fdldasz6h8sbn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylyay41fdldasz6h8sbn.png" alt="Telerik Rich TextBox on Linux"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Startup License
&lt;/h2&gt;

&lt;p&gt;The launch of Avalonia XPF trials signifies a new phase in our journey. But we're not stopping there. We've always aimed to make Avalonia's robust solutions accessible to a diverse range of developers and businesses, which is why we are thrilled to introduce the new Startup license.&lt;/p&gt;

&lt;p&gt;Our initial vision for Avalonia XPF was to offer large enterprises a way to conserve valuable resources while extending their application's reach. We wanted to help companies save months, or even years, of work rewriting applications. To our delight, we found that the appeal of Avalonia XPF extended beyond large corporations. Many smaller companies have also expressed a keen interest in our technology. To accommodate these smaller companies and startups, we're offering an Startup license.&lt;/p&gt;

&lt;p&gt;With significantly reduced costs, the Startup license is designed for companies with no more than five employees and annual revenues not exceeding 1 million USD. This license, while highly affordable, includes up to ten support tickets per year. We are confident that the Startup license will enable many more businesses to experience the transformative benefits of Avalonia XPF.&lt;/p&gt;

&lt;p&gt;With Avalonia XPF and the introduction of the Startup license, we're not just expanding platforms and licensing options; we're expanding horizons, possibilities, and opportunities. We believe that with the right tools, developers and companies, regardless of their size, can build upon their existing WPF investments and increase their reach.&lt;/p&gt;

&lt;p&gt;If you have a WPF application and are interested in exploring what Avalonia XPF can do for you, we would love to hear from you. Reach out to us, and let's embark on this exciting journey together.&lt;/p&gt;

&lt;p&gt;To the future of WPF, we say: the future is here, the future is Avalonia XPF.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>wpf</category>
    </item>
    <item>
      <title>Avalonia for Visual Studio Code (Early Access)</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Thu, 27 Jul 2023 07:09:15 +0000</pubDate>
      <link>https://dev.to/avalonia/avalonia-for-visual-studio-code-early-access-34bh</link>
      <guid>https://dev.to/avalonia/avalonia-for-visual-studio-code-early-access-34bh</guid>
      <description>&lt;p&gt;Two weeks ago we showed a &lt;a href="https://github.com/AvaloniaUI/Avalonia/discussions/12128" rel="noopener noreferrer"&gt;sneak peak&lt;/a&gt; of Avalonia for Visual Studio Code. The extension will significantly enhance the Avalonia development experience in Visual Studio Code. It features our XAML code completion and integrated XAML previewer, making it easier than ever to build beautiful Avalonia apps.&lt;/p&gt;

&lt;p&gt;Today, we are excited to invite you, the sponsors and the members of OpenCollective to try the (extremely) early build of the extension!&lt;/p&gt;

&lt;p&gt;Please sign up for the early access &lt;a href="https://forms.gle/UUmEdEVpMpET3pvh8" rel="noopener noreferrer"&gt;here&lt;/a&gt;, we will start sending out instructions from the 27th of July.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s in the extension?
&lt;/h2&gt;

&lt;p&gt;The extension aims to bring the most common workflows for Avalonia developers. However, the preview will enable the two most common scenarios to kick off the support for VSCode&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrated XAML Previewer
&lt;/h2&gt;

&lt;p&gt;The Avalonia XAML Previewer is a powerful tool that allows you to visualise XAML code in real-time. It enables you to efficiently design and fine-tune user interfaces, helping to identify potential issues and visualise the impact of changes instantly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft93kbadlnukd54gzwsut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft93kbadlnukd54gzwsut.png" alt="Screenshot of the VSCode Extension running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  XAML Code completion
&lt;/h2&gt;

&lt;p&gt;The Avalonia XAML in the VS Code is powered by the same code completion engine available for Visual Studio on Windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sphyckhviplxmqpqra8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sphyckhviplxmqpqra8.png" alt="XAML Completion in VSCode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rich syntax highlighter and contextual code complete will make it lot easier to read and write XAML files&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback
&lt;/h2&gt;

&lt;p&gt;Please share your suggestions, feature requests and report issues for the extension through VS Code’s Help &amp;gt; Report Issue dialog&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5jl0wjly1tpo3z4080d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5jl0wjly1tpo3z4080d.png" alt="VSCode Feedback Dialog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can follow all the suggestions and issues the extension &lt;a href="https://github.com/avaloniaUI/Avalonia-vscode-extension/issues" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>ui</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Welcome to the New Era of App Development: Introducing Avalonia v11</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Wed, 05 Jul 2023 10:26:52 +0000</pubDate>
      <link>https://dev.to/avalonia/welcome-to-the-new-era-of-app-development-introducing-avalonia-v11-4na7</link>
      <guid>https://dev.to/avalonia/welcome-to-the-new-era-of-app-development-introducing-avalonia-v11-4na7</guid>
      <description>&lt;p&gt;Today, we are thrilled to announce the release of Avalonia 11.0! &lt;/p&gt;

&lt;p&gt;After nearly a year in preview and countless thousands of hours of dedication, it is time to unleash a game-changer in cross-platform application development. Avalonia v11 embodies a huge leap forward in our goal to provide developers with an efficient, feature-rich, and seamless experience to create exceptional UIs across all major platforms.&lt;/p&gt;

&lt;p&gt;What makes Avalonia v11 a milestone in our journey? Here's a peek into the wealth of features we have packed into this revolutionary version:&lt;/p&gt;

&lt;h2&gt;
  
  
  Broadened Horizons with New Platforms
&lt;/h2&gt;

&lt;p&gt;The broadened platform support is one of the most significant updates in v11. With this release, we've included iOS, Android, and WebAssembly support, taking our cross-platform capabilities to new horizons. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg4foir5j6angfp20x0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg4foir5j6angfp20x0w.png" alt="Avalonia Solitaire sample running on WebAssembly, iOS and Android"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking to the future, we’ve also previewed support for &lt;a href="https://developer.apple.com/visionos/" rel="noopener noreferrer"&gt;Apple's visionOS&lt;/a&gt; and seen our incredible community work to enable Avalonia UI on &lt;a href="https://www.samsung.com/my/explore/entertainment/tizen-os-samsung-smart-tvs-that-are-worth-buying/" rel="noopener noreferrer"&gt;Samsung's TizenOS&lt;/a&gt;!  Our unique architecture enables us to add new platforms with ease, which we &lt;a href="https://avaloniaui.net/Blog/avalonia-platform-support-why-it-s-simple,ca378b03-fb47-4c34-a347-182acaa43d05" rel="noopener noreferrer"&gt;wrote about last year&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyt0akp1ds6gfrkmevtbs.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyt0akp1ds6gfrkmevtbs.jpeg" alt="Avalonia Solitaire sample running on visionOS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New Composition Renderer
&lt;/h2&gt;

&lt;p&gt;Our new composition renderer is a significant advancement in visual capability and performance. At its core, the composition renderer brings new animation possibilities to the table. With support for implicit animations, connected animations and render thread animations, the visual dynamism of your application can reach new heights. These features allow for smooth, high-performance animations that can enrich your user interfaces and provide engaging user experiences. &lt;/p&gt;

&lt;p&gt;Beyond the animation enhancements, the composition renderer provides substantial performance improvements. It’s designed to be highly efficient, reducing memory pressure and enabling high frame rates even on low-powered embedded devices. A testament to Avalonia's efficiency is its widespread use in embedded systems. Our architecture enables delivering a seamless user experience, even when operating on 20-year-old embedded CPUs. This level of performance optimization is rare, demonstrating Avalonia's ability to adapt to diverse hardware configurations while maintaining smooth, responsive applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Text Rendering and Layout
&lt;/h2&gt;

&lt;p&gt;Avalonia v11 ushers in a new era of text rendering capabilities, significantly enhancing control and flexibility over the visual elements in your UI. We’ve introduced rich text rendering that supports inline elements. This feature allows for dramatic variations in a single TextBlock, from changing font styles to adding hyperlinks, or even embedding controls - something that wasn’t previously achievable. &lt;/p&gt;

&lt;p&gt;These improvements and capabilities set the foundation for full rich text editing, a feature we’re excited to explore in the upcoming versions of Avalonia. &lt;/p&gt;

&lt;h2&gt;
  
  
  IME Support
&lt;/h2&gt;

&lt;p&gt;Our commitment to global reach and inclusivity has led to the introduction of &lt;a href="https://en.wikipedia.org/wiki/Input_method" rel="noopener noreferrer"&gt;Input Method Editor&lt;/a&gt; (IME) support in v11. This vital feature assists users in entering characters and symbols not found on their input devices. IME support also enables seamless integration with on-screen keyboards on mobile and web platforms. This means that Avalonia apps now play nicely with features such as auto-completions and other OS provided text features. As a result, Avalonia apps are become even more user-friendly and adaptable to a range of input methods. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdk6wzftv77ragauioej6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdk6wzftv77ragauioej6.jpeg" alt="Avalonia Control Catalog running on visionOS, demonstrating IME features for text entry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility Support
&lt;/h2&gt;

&lt;p&gt;We believe that technology should be inclusive and accessible to all. Therefore, we're excited to introduce our new accessibility support, which ensures that Avalonia applications can be used and enjoyed by everyone, including those with disabilities.&lt;/p&gt;

&lt;p&gt;We've laid the groundwork for full accessibility support, implementing critical features that make apps more accessible to users with visual, motor, or cognitive disabilities. These enhancements comply with industry standards and guidelines, making Avalonia a more attractive choice for developers concerned with building accessible software.&lt;/p&gt;

&lt;p&gt;We've made strides in keyboard navigation, screen reader support, and high-contrast themes. And while we're proud of our progress, we consider this to be just the beginning. We're committed to continuously improving the accessibility of Avalonia, making it easier for everyone to use the applications built with our framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automated Testing
&lt;/h2&gt;

&lt;p&gt;We’ve overhauled our automated testing capabilities to ensure you can develop robust and reliable applications with ease. This release introduces support for automated testing that extends beyond the Avalonia test environment to include traditional testing frameworks like &lt;a href="https://appium.io/docs/en/2.0/" rel="noopener noreferrer"&gt;Appium&lt;/a&gt;. With v11, you can take advantage of the testing tools you’re already familiar with to ensure your application runs flawlessly across platforms. &lt;/p&gt;

&lt;p&gt;But the enhancements to our testing capabilities go even further. With the introduction of a ‘Headless’ mode, you can run your entire application and execute tests on it at incredibly high speed. This headless mode streamlines the testing process, enabling you to validate functionality and detect bugs more efficiently than ever before. This is a monumental leap forward in our testing capabilities, and we believe it will dramatically improve your development workflow. &lt;/p&gt;

&lt;h2&gt;
  
  
  Control Themes
&lt;/h2&gt;

&lt;p&gt;One of the notable enhancements in v11 is the significant improvements made to our control themes. While we've always prided ourselves on the customizability offered by Avalonia, in this version, we've taken it a step further to provide developers with even more flexibility and control over the look and feel of their applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdfoqr5jhaizddqv20ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdfoqr5jhaizddqv20ls.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Control themes in v11 have been restructured for easier customization, which is particularly beneficial if you have a precise, consistent visual identity you'd like to maintain across your applications. This ease of customization also increases efficiency, enabling you to achieve the desired aesthetic with less time and effort.&lt;/p&gt;

&lt;p&gt;Additionally, we've improved our support for theme switching, allowing your users to switch between light and dark modes or other custom themes you provide seamlessly and dynamically.&lt;/p&gt;

&lt;h2&gt;
  
  
  AOT &amp;amp; Trimming
&lt;/h2&gt;

&lt;p&gt;We're excited to announce that v11 fully supports Ahead-of-Time (AOT) compilation and trimming, resolving issues from previous versions. The updated trimming functionality eliminates unused code during the publishing process, dramatically reducing application sizes. With v11, developers can now experience  ~60% smaller application sizes, providing faster downloads, quicker startup times, and less end-user storage used. &lt;/p&gt;

&lt;h2&gt;
  
  
  Revamped Developer Documentation
&lt;/h2&gt;

&lt;p&gt;Your feedback has been invaluable, and we’ve heard you loud and clear about improving our documentation! We’re thrilled to reveal that we’ve transitioned our documentation from GitBook to a new custom platform that aligns more precisely with our evolving needs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0w9q73boqgfb5awly6j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0w9q73boqgfb5awly6j.png" alt="A screenshot of the new Avalonia documentation portal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This significant step forward offers us enormous flexibility for future enhancements. The goal is to continually adopt and refine the documentation to better serve our expanding community. &lt;/p&gt;

&lt;p&gt;We’ve also worked on creating &lt;a href="https://github.com/AvaloniaUI/AvaloniaUI.QuickGuides" rel="noopener noreferrer"&gt;quick-guides&lt;/a&gt;, which are focused example applications that demonstrate specific functionalities.&lt;/p&gt;

&lt;p&gt;We hope to see more participation from the community to help us improve documentation. This doesn’t necessarily mean writing documentation yourself - although that would be welcome. Equally important is sharing your experiences. Tell us about the areas where you encountered hurdles, or where our current documentation fell short in supporting your journey. This kind of feedback is immensely valuable and helps us understand where to focus our improvement efforts. Every contribution, whether big or small, goes a long way in refining Avalonia into an even more developer-friendly framework. &lt;/p&gt;

&lt;h2&gt;
  
  
  Template Studio
&lt;/h2&gt;

&lt;p&gt;We’ve released our first version of &lt;a href="https://github.com/AvaloniaUI/TemplateStudio" rel="noopener noreferrer"&gt;Template Studio for Avalonia&lt;/a&gt; - a streamlined solution designed to accelerate the creation of new Avalonia apps using an intuitive, wizard-based UI. &lt;/p&gt;

&lt;p&gt;Getting started with Template Studio for Avalonia is a breeze. Simply install &lt;a href="https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.TemplateStudioForAvalonia" rel="noopener noreferrer"&gt;the extension&lt;/a&gt; and select the Template Studio project template when creating a new project in Visual Studio.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1rpuhdjula6c1z8opbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1rpuhdjula6c1z8opbp.png" alt="A screenshot of Template Studio for Avalonia"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem Growth
&lt;/h2&gt;

&lt;p&gt;We've had the privilege of working closely with a range of pro-control vendors who have been developing specifically for Avalonia. &lt;/p&gt;

&lt;p&gt;This marks an important milestone in Avalonia's journey as it signals a shift in the broader ecosystem - attracting commercial interest from vendors who have previously dedicated their efforts to supporting WPF, Xamarin and other Microsoft UI toolkits. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm1mvryrcoieennd4lyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm1mvryrcoieennd4lyb.png" alt="A screenshot of ActiPro's sample app for Avalonia"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We’ve examined various .NET-based cross-platform UI frameworks for our next set of UI controls, but none of them capture the magic of WPF in the way that Avalonia does. Avalonia has a very strong community, offers pixel-perfect rendering on a multitude of platforms, is easy to customize, and frankly is a joy to work with.&lt;br&gt;
&lt;strong&gt;Bill Henning, President, Actipro Software&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's exciting and humbling to observe this growth and be part of the vibrant community that is driving it. We're immensely grateful for the collaboration of these vendors and their belief in Avalonia's potential. As we move forward, we're enthusiastic about future collaborations and the continuing growth of Avalonia's ecosystem. &lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you!
&lt;/h2&gt;

&lt;p&gt;Avalonia has always been a labour of love, a community-driven project open to all. Over the past decade, more than &lt;a href="https://github.com/AvaloniaUI/Avalonia/graphs/contributors" rel="noopener noreferrer"&gt;300 contributors&lt;/a&gt; worldwide have shaped Avalonia into what it is today. Avalonia v11 is not just a new version; it embodies our vibrant community's collective hard work and ambition to create the best cross-platform UI framework. &lt;/p&gt;

&lt;p&gt;We invite you to join us on this exciting journey and help shape the next decade of Avalonia and the future of cross-platform .NET app development. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Ready to dive into Avalonia v11 and explore all the amazing new features? Head over to our &lt;a href="https://avaloniaui.net/GettingStarted" rel="noopener noreferrer"&gt;Get Started&lt;/a&gt; guide to begin building with Avalonia. &lt;/p&gt;

&lt;p&gt;If you’re already developing with Avalonia and want to upgrade to v11 then check out our &lt;a href="https://docs.avaloniaui.net/docs/next/stay-up-to-date/upgrade-from-0.10" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>ui</category>
      <category>xamarin</category>
      <category>csharp</category>
    </item>
    <item>
      <title>First Release Candidate of Avalonia UI v11 Now Available!</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Thu, 01 Jun 2023 05:10:03 +0000</pubDate>
      <link>https://dev.to/avalonia/first-release-candidate-of-avalonia-ui-v11-now-available-34c8</link>
      <guid>https://dev.to/avalonia/first-release-candidate-of-avalonia-ui-v11-now-available-34c8</guid>
      <description>&lt;p&gt;We're excited to announce that the first Release Candidate (RC) of Avalonia UI v11 is now available for you to try out!&lt;/p&gt;

&lt;p&gt;This RC marks a significant milestone for us as it stabilises the API. It's been a journey of intense work, learning, and collaboration. And now, we can confidently say that we're closer than ever to the final release of v11&lt;/p&gt;

&lt;p&gt;Now is the perfect time for you and your teams to test drive v11. As we progress, the only changes we're looking at are bug fixes. We believe this makes the RC a safe and exciting option to explore, especially if you're considering the upcoming production releases.&lt;/p&gt;

&lt;p&gt;With a keen focus on maintainability, Avalonia UI v11 carries the most substantial changes in our API to date, setting the project up for a thriving future. We've poured considerable thought, time, and resources to ensure these changes pave the way for a more robust and reliable Avalonia UI. While this release represents our most substantial set of breaking changes, we expect future major releases will see significantly fewer breaking API changes.&lt;/p&gt;

&lt;p&gt;As part of these breaking API changes, some previously public classes are now marked as 'Internal'. This change has been done to safeguard the integrity of applications by allowing us to modify implementations without introducing future breaking changes. While we've taken every measure to ensure a smooth transition, we acknowledge that you might encounter scenarios where a critical class is no longer visible. If you encounter such instances, we strongly encourage you to contact us. We're open to a dialogue about changing certain classes back to public visibility based on your valuable feedback.&lt;/p&gt;

&lt;p&gt;We encourage everyone to try out the RC, provide your feedback, and help us make Avalonia UI v11 the best. We sincerely thank all our users, contributors, and the entire Avalonia community for your ongoing support.&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://www.nuget.org/packages/Avalonia/11.0.0-rc1.1"&gt;nuget&lt;/a&gt; to get started. Let's build the future of cross-platform .NET UI technology together!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>opensource</category>
      <category>ui</category>
    </item>
    <item>
      <title>Avalonia UI and MAUI - Something for everyone</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Wed, 29 Mar 2023 11:40:11 +0000</pubDate>
      <link>https://dev.to/avalonia/avalonia-ui-and-maui-something-for-everyone-1a3d</link>
      <guid>https://dev.to/avalonia/avalonia-ui-and-maui-something-for-everyone-1a3d</guid>
      <description>&lt;p&gt;In the world of cross-platform .NET development, two popular frameworks have emerged as strong contenders: &lt;a href="https://avaloniaui.net/" rel="noopener noreferrer"&gt;Avalonia UI&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/dotnet/maui/what-is-maui?view=net-maui-7.0" rel="noopener noreferrer"&gt;.NET MAUI&lt;/a&gt; (Multi-platform App UI). Both are powerful tools designed to solve different problems, making it essential to understand their key differences to make an informed choice for your project. &lt;/p&gt;

&lt;p&gt;This blog post will delve into the primary distinction between these two technologies and the benefits of each approach.&lt;/p&gt;

&lt;p&gt;Let's start with a brief overview of both Avalonia UI and MAUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avalonia UI
&lt;/h2&gt;

&lt;p&gt;Avalonia UI is an &lt;a href="https://github.com/avaloniaui/avalonia" rel="noopener noreferrer"&gt;open-source&lt;/a&gt;, cross-platform UI framework that allows developers to create beautiful, responsive applications using a single codebase for multiple platforms, including Windows, macOS, Linux (desktop and embedded), WebAssembly and even mobile platforms. Avalonia UI leverages XAML for creating the UI, making it familiar to those with experience in WPF, UWP, WinUI or Xamarin.Forms. &lt;/p&gt;

&lt;p&gt;While Avalonia UI is free and OSS, it is backed by a small, independent company formed by the core team responsible for the development of Avalonia UI. We offer &lt;a href="https://avaloniaui.net/Services" rel="noopener noreferrer"&gt;development services&lt;/a&gt;, &lt;a href="https://avaloniaui.net/Support" rel="noopener noreferrer"&gt;support agreements&lt;/a&gt; and recently announced our first product, &lt;a href="https://avaloniaui.net/XPF" rel="noopener noreferrer"&gt;Avalonia XPF&lt;/a&gt;. The goal of the company is to generate revenue to enable the core team to work on Avalonia UI full-time and to better serve enterprises building apps with Avalonia. &lt;/p&gt;

&lt;h2&gt;
  
  
  MAUI
&lt;/h2&gt;

&lt;p&gt;MAUI (Multi-platform App UI) is an evolution of Xamarin.Forms. It's an &lt;a href="https://github.com/dotnet/maui" rel="noopener noreferrer"&gt;open-source&lt;/a&gt;, cross-platform framework for building native UIs for iOS, Android, macOS, and Windows. MAUI simplifies creating apps with native user interfaces by enabling developers to develop in a single project. It uses the native UI toolkit of each platform, which allows developers to leverage platform-specific capabilities and build applications that feel native to each platform.&lt;/p&gt;

&lt;p&gt;Developed by Microsoft, it has a large and dedicated community of users to lean on for support. &lt;/p&gt;

&lt;p&gt;Now that we have a basic understanding of Avalonia UI and MAUI, let's dive deeper into their differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI Drawing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Native vs Custom Rendering:
&lt;/h3&gt;

&lt;p&gt;The primary difference between Avalonia UI and MAUI lies in how they draw the user interface. Avalonia UI employs a custom drawing engine powered by Skia (like Flutter), while MAUI uses native UI toolkits for each platform. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr5d6xbygejsi4f6pw0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr5d6xbygejsi4f6pw0i.png" alt="Architecture overview of MAUI and Avalonia UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's explore these approaches in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  MAUI
&lt;/h3&gt;

&lt;p&gt;MAUI uses the native UI toolkit of each platform, resulting in an application that feels native to the platform it's running on. This means that a MAUI app on Android will use the native Android UI toolkit, while on iOS, it will use UIKit. This approach ensures that your application will have a look and feel that users expect on their devices. This approach offers several benefits:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: By utilising native UI toolkits, MAUI can offer good performance, especially on mobile devices. It should be noted that on some platforms, objects will exist in both the .NET memory space and the platform UI toolkits memory. This can have a noticeable effect on performance compared to an app developed purely with the native technology. For example, on Android you will have two Garbage Collectors, one for the ART Runtime and one for the .NET runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform-Specific Animations and Transitions&lt;/strong&gt;: MAUI allows developers to harness platform-specific animations and transitions, giving applications a polished and native feel. By utilising the animations provided by the native UI toolkits, developers can create applications that are consistent with the design language of each platform and provide a familiar user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rapid Adoption of New Platform Features&lt;/strong&gt;: As new features and UI components are introduced in native platforms, MAUI applications can quickly adopt these updates, ensuring that applications stay up-to-date with the latest design trends and platform improvements. This helps maintain a modern and consistent user experience while also reducing the time and effort needed to implement new features manually. &lt;/p&gt;

&lt;h3&gt;
  
  
  Avalonia UI
&lt;/h3&gt;

&lt;p&gt;Unlike MAUI, Avalonia UI uses a custom rendering engine that draws UI elements consistently across all platforms. This means that your application will have the same appearance and behaviour regardless of the platform it's running on. Avalonia UI's custom rendering approach allows for greater control over the UI design and a consistent user experience across different platforms. This approach comes with its own set of benefits: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: Applications built with Avalonia UI have a consistent look and feel across platforms, which can be valuable for branding and user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: The custom drawing engine gives developers more control over their application's appearance and behaviour. They can create custom UI elements and styles that might not be possible or would require more effort using native UI toolkits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplified Maintenance&lt;/strong&gt;: Using a custom drawing engine means the UI code is the same across all platforms, simplifying maintenance and updates. Developers only need to change the shared codebase, reducing the time and effort required to maintain the application across multiple platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independent Evolution&lt;/strong&gt;: Avalonia UI's custom drawing engine allows the framework to evolve independently of the native platforms it targets. This means that improvements, bug fixes, and new features can be implemented faster without having to wait for native platforms to catch up or maintain compatibility. As a result, Avalonia UI applications can benefit from continuous innovation and stay ahead of the curve in terms of UI and UX advancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform Support
&lt;/h2&gt;

&lt;p&gt;While both technologies are both versatile and powerful UI frameworks, their platform support differs in some key areas. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;br&gt;
MAUI provides support for Windows 10 and 11, depending on WinUI3, while Avalonia UI can target Windows 7 and higher. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;br&gt;
As MAUI relies on Mac Catalyst, it supports macOS 10.15 (Catalina) and newer. Avalonia, on the other hand, supports macOS 10.13 (High Sierra) and higher. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;br&gt;
At this time, MAUI doesn’t have any official support for Linux, though a community effort exists to enable MAUI to run on desktop Linux. Avalonia UI supports both desktop and embedded distributions of Linux, requiring no desktop environment to be installed. Officially supported distributions include Debian 9, Ubuntu 16.04 and Fedora 30 and higher. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;br&gt;
MAUI supports iOS 11 and higher, while Avalonia UI supports iOS 13.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;br&gt;
MAUI supports Android 7.0 (API 24) and higher, while Avalonia UI supports Android 5 (API 21)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebAssembly&lt;/strong&gt;&lt;br&gt;
It was recently announced that MAUI could be getting Web support after .NET 8, but at this time, there are no options to deploy your MAUI applications to the web. Avalonia UI supports WebAssembly today and has a &lt;a href="https://play.avaloniaui.net/" rel="noopener noreferrer"&gt;fully interactive playground&lt;/a&gt; for exploring Avalonia UI on the web. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solving Problems Differently
&lt;/h2&gt;

&lt;p&gt;While both Avalonia UI and MAUI are powerful frameworks for cross-platform development, they are designed to address different concerns:&lt;/p&gt;

&lt;p&gt;Avalonia UI is an excellent choice for developers who prioritise consistent branding and a uniform user experience across platforms. Its custom drawing engine provides flexibility in designing custom UI components and styles, making it perfect for creating unique and visually rich applications. Avalonia UI excels on desktop focused applications, with mobile and WebAssembly being new additions to the platform. &lt;/p&gt;

&lt;p&gt;On the other hand, MAUI is the go-to choice for developers who need their applications to adhere to platform-specific design guidelines and provide a native look and feel. Its use of native UI toolkits ensures fantastic performance on various devices, and direct access to platform-specific APIs allows for seamless integration of native functionality. MAUI is a great choice for developing mobile centric applications, where desktop is a secondary or lower priority. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Avalonia UI and MAUI are both outstanding options for cross-platform development, each offering unique benefits depending on your project's requirements. The strength of the .NET ecosystem lies in its ability to provide developers with an array of options to choose from, ensuring they can select the most suitable approach for their specific project. The beauty of .NET is that a well architected application can reuse a huge amount of code, regardless of the UI framework used. &lt;/p&gt;

&lt;p&gt;If you want to learn more about Avalonia UI and how it can help you develop visually stunning, high-performance applications for Windows, macOS, Linux, Android, iOS and WebAssembly then check out our &lt;a href="https://avaloniaui.net/GettingStarted" rel="noopener noreferrer"&gt;getting started&lt;/a&gt;.  &lt;/p&gt;

</description>
      <category>avaloniaui</category>
      <category>dotnet</category>
      <category>maui</category>
      <category>crossplatform</category>
    </item>
    <item>
      <title>Avalonia platform support - why it's simple</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Fri, 03 Jun 2022 10:25:27 +0000</pubDate>
      <link>https://dev.to/avalonia/avalonia-platform-support-why-its-simple-cjd</link>
      <guid>https://dev.to/avalonia/avalonia-platform-support-why-its-simple-cjd</guid>
      <description>&lt;p&gt;I recently came across a developer discussing Avalonia on Discord who was conflating the wide range of platforms Avalonia supports with a significant increase in development effort. I thought it would be interesting to briefly explore how Avalonia works and explain why bringing Avalonia to new platforms isn't nearly as involved as some might imagine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How does it compare to MAUI?&lt;/strong&gt;&lt;br&gt;
Before we go too far, it's essential to understand that Avalonia works very differently from frameworks like MAUI (or Xamarin.Forms), which uses a platform's native UI toolkit, providing a common API across all the supported platforms. MAUI is less a UI toolkit; more an abstraction layer over existing toolkits. The task of rendering the UI and handling user interactions isn't something the MAUI development team needs to worry about, as the device's UI toolkit is responsible for this. Instead, the primary problem for the MAUI development team has been creating an abstraction that conceals the wildly different UI toolkits, each with its quirks. Think of MAUI as a wrapper that provides native controls in an easy to use and lowest common denominator API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avalonia - Making Pixel-Perfect Apps
&lt;/h2&gt;

&lt;p&gt;Having established how MAUI works, let's examine how Avalonia's architecture and approach differ. It's worth knowing that Avalonia is in good company in its design and isn't altogether unique as it shares similarities with how Google's Flutter UI toolkit works. &lt;/p&gt;

&lt;p&gt;The most significant similarity is that Avalonia also utilises its own renderer, backed either by &lt;a href="https://skia.org/" rel="noopener noreferrer"&gt;Skia&lt;/a&gt; or &lt;a href="https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-portal" rel="noopener noreferrer"&gt;Direct2D&lt;/a&gt;. The renderer is responsible for drawing the entire application, allowing Avalonia to avoid depending on a device's UI toolkit. &lt;/p&gt;

&lt;p&gt;To illustrate why this is significant, we should consider embedded and low-powered devices. Avalonia has become particularly popular among manufacturers producing touch-based embedded industrial devices. &lt;/p&gt;

&lt;p&gt;We've found that they'll often use Linux, opting not to install a desktop environment, which would waste the limited storage, memory and CPU available on their low-powered devices. They can do this because Avalonia supports both accelerated rendering via &lt;a href="https://en.wikipedia.org/wiki/Direct_Rendering_Manager" rel="noopener noreferrer"&gt;Direct Rendering Manager&lt;/a&gt; and a software &lt;a href="https://en.wikipedia.org/wiki/Linux_framebuffer" rel="noopener noreferrer"&gt;framebuffer&lt;/a&gt;. Given it’s  using the same kernel API’s used internally by &lt;a href="https://wiki.archlinux.org/title/xorg" rel="noopener noreferrer"&gt;Xorg&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Wayland_(display_server_protocol)" rel="noopener noreferrer"&gt;Wayland&lt;/a&gt; compositors, it essentially replaces Xorg/Wayland, gaining exclusive access to the graphics hardware. &lt;/p&gt;

&lt;p&gt;Beyond industrial device manufacturing, this approach brings countless other benefits, such as ensuring that an app looks and behaves identically across all the supported platforms. The ability to customise any part of the UI for any particular platform is maintained and is as simple as altering XAML styles. With Avalonia, creating great-looking, cross-platform apps without needing to use platform-specific UI APIs for the various devices you're supporting is easy. It's the essence of "write once, run everywhere".&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The architecture diagram below gives a good overview of how Avalonia works. Note that the majority of functionality in Avalonia resides in a netstandard2.0 project! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5q7x1d628kcb1d4g09g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx5q7x1d628kcb1d4g09g.png" alt="Overview of the Avalonia Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rendering an application's user interface is just one piece of the puzzle. Avalonia also needs to handle elements such as wiring up the clipboard, windowing, cursors, hardware acceleration and input events. These pieces of the puzzle are required to facilitate Avalonia on a new platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform Support
&lt;/h2&gt;

&lt;p&gt;Regardless of the intricacies required to create a UI toolkit, between 10 and 15 percent of the Avalonia code relates to facilitating the platforms. Most of the code is agnostic to any platform, meaning it's relatively easy for us to bring Avalonia support to new platforms when we want. &lt;/p&gt;

&lt;p&gt;At the fundamental level, supporting a new platform with Avalonia requires two things; the ability to draw pixels and receive input events. &lt;/p&gt;

&lt;h2&gt;
  
  
  Avalonia VNC
&lt;/h2&gt;

&lt;p&gt;To demonstrate this point, let's look at the &lt;a href="https://github.com/AvaloniaUI/Avalonia/tree/master/src/Avalonia.Headless.Vnc" rel="noopener noreferrer"&gt;Avalonia VNC platform support&lt;/a&gt;. While not typically considered a platform in its own right, in the context of Avalonia, VNC meets the prerequisites of being able to draw pixels and receive input events. It can thus be considered a platform! &lt;/p&gt;

&lt;p&gt;What's especially surprising about the Avalonia VNC platform support is its implementation stands at less than 200 lines of code! It demonstrates just how little code is required to enable a new platform! &lt;/p&gt;

&lt;p&gt;Why does Avalonia support VNC in the first place? Well, it's valuable for a few reasons, with my favourite being it enabled very early testing of web support. Before WASM with Blazor were viable options for enabling Avalonia in the browser, it was possible to run an embedded VNC server serving Avalonia content, delivering rudimentary web support. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While Avalonia has been historically focused on the desktop for almost a decade now, the recently released preview of iOS, Android and Web support represents a new milestone for the project. Supporting these platforms was never a technical problem or a matter of developer resources. &lt;/p&gt;

&lt;p&gt;The developers contributing to Avalonia have helped create a cross-platform UI framework that industry leaders such as GitHub, Unity and JetBrains have come to trust. Given the project's remarkable success and massive growth in contributors, it presents an excellent opportunity to look to the future and consider how we can improve mobile and web development. &lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://avaloniaui.net/" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.avaloniaui.net/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/avaloniaui" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>mobile</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Storing Desktop App Data</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Wed, 13 Jan 2021 16:51:40 +0000</pubDate>
      <link>https://dev.to/mikecodesdotnet/storing-desktop-app-data-1g4c</link>
      <guid>https://dev.to/mikecodesdotnet/storing-desktop-app-data-1g4c</guid>
      <description>&lt;p&gt;I like to think of my PC’s document directory as a sacred place. As its name suggests, the documents directory is where I store my documents, in a neatly organised set of subdirectories.&lt;/p&gt;

&lt;p&gt;It is not a dumping ground for random files and folders; this is what I use my desktop for!&lt;/p&gt;

&lt;p&gt;I find it somewhat aggravating that so many desktop applications developers pollute the divined documents directory with their application-specific data. I hope that after reading this post, any offending developers will reconsider their choices and make better decisions on their next app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Special Folders
&lt;/h2&gt;

&lt;p&gt;Microsoft was kind enough to grace our hard drives with special folders such as My Music and My Pictures. These are just two of the 48 special directories defined in the &lt;a href="https://docs.microsoft.com/dotnet/api/system.environment.specialfolder?view=net-5.0&amp;amp;WT.mc_id=dotnet-desktop-mijam"&gt;‘Environment.SpecialFolder‘&lt;/a&gt;&lt;br&gt;
 enum, part of the ‘System‘ namespace.&lt;/p&gt;

&lt;p&gt;Two of my most used SpecialFolders are &lt;strong&gt;&lt;em&gt;ApplicationData&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;CommonApplicationData&lt;/em&gt;&lt;/strong&gt;. &lt;em&gt;ApplicationData&lt;/em&gt; is for application-specific data for the current roaming user, and &lt;em&gt;CommonApplicationData&lt;/em&gt; is for application-specific data that is used by all users.&lt;/p&gt;

&lt;p&gt;So, when you build your next fantastic desktop application, I implore you to consider using one of these special folders for your application-specific content, rather than polluting your user’s document directory. It’s super easy to use!&lt;/p&gt;

&lt;h4&gt;
  
  
  Show me the code!
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateApplicationSpecificGuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;directoryName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;appDataPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetFolderPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SpecialFolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myAppsDataDirPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appDataPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;directoryName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myAppsDataDirPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to deal with existing pollution?
&lt;/h3&gt;

&lt;p&gt;When I find applications that absolutely must have their app-specific data in the document’s directory, I tend to set their directories to Hidden. Out of sight, out of mind.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Distributed DMX with Apache Ignite</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Wed, 04 Mar 2020 11:42:54 +0000</pubDate>
      <link>https://dev.to/dotnet/distributed-dmx-with-apache-ignite-2a8f</link>
      <guid>https://dev.to/dotnet/distributed-dmx-with-apache-ignite-2a8f</guid>
      <description>&lt;p&gt;A little known fact is that the original, intelligent lights and programming hardware formed a distributed system. Each light had its own on-board memory which was used to store the different states (looks) used throughout the show, and the lighting console would send a command for each light to load a particular look. I’ve heard of a show that was too large to fit on the lights on-board memory, so the operator had to split the programming into two, using the interval to upload the second half. I can’t imagine how nervous they were during this process!&lt;/p&gt;

&lt;p&gt;This approach was a good start into the world of intelligent lighting, but had some significant drawbacks, the biggest being the impossibility of programming the show ahead of arriving at the venue. This ruled out the option of using 3D tools like &lt;a href="http://www.capture.se/"&gt;Capture &lt;/a&gt;to program shows using a virtual representation of the venue and lighting rig.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q-PJq9sK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/img_0327.jpg%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q-PJq9sK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/img_0327.jpg%3Fw%3D1024" alt=""&gt;&lt;/a&gt;An old Lighting Design I created many years ago, using Capture&lt;/p&gt;

&lt;p&gt;Fast forward a little, and the advancements in consumer CPU’s allowed a single device to calculate all the required control data fast enough that distributed systems were no longer needed. This saw manufacturers adopt the architecture of using a single lighting console to calculate everything, with some providing the ability to track its state on a backup / redundant console but none offering a distributed system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mSSgeeqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/backupdmxtopology.jpg%3Fw%3D900" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mSSgeeqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/backupdmxtopology.jpg%3Fw%3D900" alt=""&gt;&lt;/a&gt;The backup console does no computation &lt;/p&gt;

&lt;h4&gt;
  
  
  Coming Full Circle
&lt;/h4&gt;

&lt;p&gt;Only relativity recently has distributed systems come back into vogue, as shows have become more and more complex. With the complexity of shows like Eurovision, a single lighting console cannot calculate the control data fast enough. To get around this, multiple consoles are used together to control these massive shows. These console’s don’t just have ownership of a subsection of the lights, but instead create a &lt;a href="https://en.wikipedia.org/wiki/Grid_computing"&gt;Compute Grid&lt;/a&gt;, which is a high-performance computing technique to create a virtual supercomputer. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Grids are a form of &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing"&gt;distributed computing&lt;/a&gt; whereby a “super virtual computer” is composed of many networked &lt;a href="https://en.wikipedia.org/wiki/Loose_coupling"&gt;loosely coupled&lt;/a&gt; computers acting together to perform very large tasks&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="https://en.wikipedia.org/wiki/Grid_computing" rel="nofollow"&gt;&lt;/a&gt;&lt;a href="https://en.wikipedia.org/wiki/Grid_computing"&gt;https://en.wikipedia.org/wiki/Grid_computing&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article, I’m going to discuss how I’m using &lt;a href="https://ignite.apache.org/"&gt;Apache Ignite&lt;/a&gt; to develop a distributed data and compute grid in order to provide high-availability and scalablity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apache Ignite
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BcTvLYZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/1200px-apache_ignite_logo.png%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BcTvLYZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/1200px-apache_ignite_logo.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What is it?
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://ignite.apache.org/"&gt;Apache Ignite&lt;/a&gt; is an in-memory computing platform that is &lt;a href="https://apacheignite-net.readme.io/docs/durable-memory"&gt;durable&lt;/a&gt;, strongly consistent, highly available and features powerful &lt;a href="https://apacheignite-net.readme.io/docs/sql-database"&gt;SQL&lt;/a&gt;, &lt;a href="https://apacheignite-net.readme.io/docs/data-grid"&gt;key-value&lt;/a&gt;, &lt;a href="https://apacheignite-net.readme.io/docs/topic-based"&gt;messaging&lt;/a&gt; and &lt;a href="https://apacheignite-net.readme.io/docs/local-and-remote-events"&gt;event &lt;/a&gt;APIs.&lt;/p&gt;

&lt;p&gt;Traditionally it’s used in industries such as e-commerce, banking, IoT and telecommunication it boasts companies such as &lt;a href="https://www.microsoft.com/"&gt;Microsoft&lt;/a&gt;, &lt;a href="https://www.apple.com"&gt;Apple&lt;/a&gt;, &lt;a href="http://www.ibm.com/"&gt;IBM&lt;/a&gt;, &lt;a href="https://www.barclays.co.uk/"&gt;Barclays&lt;/a&gt;, &lt;a href="https://www.americanexpress.com"&gt;American Express&lt;/a&gt;, &lt;a href="https://www.huawei.com"&gt;Huawei &lt;/a&gt;and &lt;a href="https://new.siemens.com"&gt;Siemens &lt;/a&gt;as users.&lt;/p&gt;

&lt;p&gt;Most users of Apache Ignite will be deploying it to servers either in a public cloud-like &lt;a href="https://azure.microsoft.com/Account/Free"&gt;Microsoft’s Azure&lt;/a&gt; or into their on-premise data centers. Though servers are the usual domain for Apache Ignite, with its &lt;a href="https://apacheignite-net.readme.io/docs/deployment"&gt;flexible deployment&lt;/a&gt; model, I can embed it as part of the Light Console&lt;a href="https://docs.microsoft.com/en-us/dotnet/core/"&gt; .NET Core&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;I’m able to develop a distributed system that provides almost unlimited horizontal scale utilising the experience of its experts in distributed systems. The Apache Ignite codebase consists of more than a million lines of code and has &lt;a href="https://github.com/apache/ignite/graphs/contributors"&gt;223 contributors&lt;/a&gt; meaning it’d be a huge effort to recreate this functionality in-house!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--quEKDQl8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/apache-graph.png%3Fw%3D738" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--quEKDQl8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/apache-graph.png%3Fw%3D738" alt=""&gt;&lt;/a&gt;Contributions to Apache Ignite&lt;/p&gt;

&lt;h4&gt;
  
  
  Clustering
&lt;/h4&gt;

&lt;p&gt;Apache Ignite is a fundamental pillar of my application architectures, providing data storage, service and event messaging capability. With being an integral part of my application, any consumer of the LightConsole.Core &lt;a href="https://support.microsoft.com/en-us/help/815065/what-is-a-dll"&gt;DLL&lt;/a&gt;will either automatically connect to an existing session or create one on launch.&lt;/p&gt;

&lt;p&gt;What this means is that anyone running the Light Console app will automatically discover existing nodes and join the cluster, thus increasing the compute and data storage resources of the overall grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--leHv4MWp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/ignitetopology.jpg%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--leHv4MWp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/ignitetopology.jpg%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using this approach means that no single device is responsible for the entire system. Instead, each node (console or onPC software) takes responsibility for a subsection of data and compute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JWTUoSUk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/untitled-project.gif%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JWTUoSUk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/untitled-project.gif%3Fw%3D1024" alt=""&gt;&lt;/a&gt;Launching a new show create a Apache Ignite Session&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed Data Storage
&lt;/h3&gt;

&lt;p&gt;Data Storage within the Light Console uses Apache Ignites distributed key-value store, which you can think of as a distributed partitioned hash map, with each console owning a portion of the overall data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nUzQWUWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/distributeddmxdata-1.jpg%3Fw%3D935" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nUzQWUWw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/distributeddmxdata-1.jpg%3Fw%3D935" alt=""&gt;&lt;/a&gt;Each instance of Light Console owns a portion of the overall data&lt;/p&gt;

&lt;p&gt;The above example demonstrates how Apache Ignite might distribute _Fixture _objects stored within the FixtureCache. In actuality, I define a backup property of 1, which will ensure that a fixture doesn’t only exist in one instance of Light Console. This is how I mitigate against data loss when a console (node) crashes or goes offline. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5uEK_0qe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/carbon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5uEK_0qe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/02/carbon.png" alt=""&gt;&lt;/a&gt;Defining a distributed Key-Value store with Apache Ignite&lt;/p&gt;

&lt;h4&gt;
  
  
  Affinity Colocation
&lt;/h4&gt;

&lt;p&gt;As the show data is distributed across instances of Light Console, it’s important to ensure that any computations that make use of the data occur on an instance of Light Console that already has a copy of the data. This is called collocation and helps to significantly improve the performance of the application by reducing the need to move data around for the network for computation. The simplest example of a collocated computation currently within the project is the Fixture Patching mechanism. This is the process of assigning &lt;a href="http://www.thedmxwiki.com/dmx_basics/dmx_addresses"&gt;DMX Addresses &lt;/a&gt;to a fixtures control channels (such as pan, tilt, colour wheel, etc..). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BVPA0btU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BVPA0btU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-8.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The&lt;a href="https://apacheignite-net.readme.io/docs/colocate-compute-and-data"&gt; Compute Action &lt;/a&gt;is invoked using the &lt;em&gt;PatchFixtureLocalCommand, _which is defined below. The _PatchFixtureLocalCommand&lt;/em&gt; hides the implementation details of the command and implements the _ILocalCommand _interface to support Undo/Redo functionality. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u5Sm8BEn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u5Sm8BEn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-9.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed Services
&lt;/h3&gt;

&lt;p&gt;Another feature of Apache Ignite that I’m using extensively is the &lt;a href="https://apacheignite-net.readme.io/docs/service-grid"&gt;Service Grid&lt;/a&gt;. Service Grid allows me to deploy services to the cluster that can be used by any of the consoles. The advantage of deploying services to the grid is that it provides continuous availability, load balancing and fault tolerance out of the box. I also have the ability to specify if a service should be a cluster-singleton, node-singleton, or key-affinity-singleton. Below you can see an example of a Node Singleton deployment, which would be deployed to each Light Console within the cluster. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hUlc3mOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/nodesingleton.png%3Fw%3D300" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hUlc3mOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/nodesingleton.png%3Fw%3D300" alt=""&gt;&lt;/a&gt;Node Singleton Service Grid Deployment. Each Console get an instance of the service.&lt;/p&gt;

&lt;p&gt;Two of the most critical services currently found within Light Console are the &lt;em&gt;PlaybackEngine&lt;/em&gt; and the_ SyncTick_ Service. Both of these services are deployed as Cluster Singletons, which means that only one instance will be running on the cluster at any given time. If the instance of Light Console which is running the service goes offline, then Apache Ignite will automatically redeploy the service to another console. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YDEQWNbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/cluster-singleton.png%3Fw%3D900" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YDEQWNbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/cluster-singleton.png%3Fw%3D900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  SyncTick Service
&lt;/h4&gt;

&lt;p&gt;The &lt;em&gt;SyncTick&lt;/em&gt; service is responsible for keeping all the currently running transitions (fades) and effects in sync with each other. This is achieved by broadcasting a tick event to all the nodes with a DateTime representing when the Tick occurred. If a transition or effect is running, upon receiving the Ticked message, it’ll calculate the next value for output and notify the &lt;em&gt;PlaybackEngine&lt;/em&gt;. With this architecture, I’m able to speed up and slow down output data / calculations across the entire grid from a single location. This makes it possible for future versions of Light Console to support &lt;a href="https://en.wikipedia.org/wiki/Timecode"&gt;Timecode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qgqlp6v7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qgqlp6v7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-11.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Messaging
&lt;/h2&gt;

&lt;p&gt;In the above snippet, you’ll notice that the Tick event is using the &lt;em&gt;SendOrdered _method of _IMessaging&lt;/em&gt;. This method allows me to ensure that the subscribers receive the Tick messages in the order that they’re sent.&lt;/p&gt;

&lt;p&gt;To subscribe to the messages, I then use the IMessaging &lt;em&gt;LocalListen _method to register a message listener object which deals what to do when a message is received. To make my life easier, I ensure that I only ever call LocalListen and I use the _EventListener _class as defined below. The&lt;/em&gt; EventListener_ class allows me to use generics for the payload and easily attach to the EventRecieved event within the subscribing class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9mZgWzVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9mZgWzVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-12.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you can see an example of a transition, which when started will create an &lt;em&gt;EventListener&lt;/em&gt; and subscribe to the &lt;em&gt;EventReceived&lt;/em&gt; event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PYSslfV4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PYSslfV4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lightconsole.files.wordpress.com/2020/03/carbon-14.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The above is just a small glimpse into how I’m using some of the feature available within Apache Ignite to power a distributed Lighting Control system. Whilst not exhaustive, I hope it gives you an idea of what’s possible and how you might also use Apache Ignite in your own projects.&lt;/p&gt;

&lt;p&gt;It’s incredibly easy to get started with given it’s available as a&lt;a href="https://www.nuget.org/packages/Apache.Ignite"&gt; Nuget package&lt;/a&gt; and has a rich set of &lt;a href="https://apacheignite-net.readme.io/docs/getting-started"&gt;documentation &lt;/a&gt;to help you understand features and how to add them to your apps.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>apacheignite</category>
      <category>distributedcompute</category>
    </item>
    <item>
      <title>Digging into App Center Data</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Tue, 18 Jun 2019 15:12:40 +0000</pubDate>
      <link>https://dev.to/mikecodesdotnet/digging-into-app-center-data-1n5n</link>
      <guid>https://dev.to/mikecodesdotnet/digging-into-app-center-data-1n5n</guid>
      <description>&lt;p&gt;I recently published a blog post discussing the introduction of  both authentication and data storage to &lt;a href="https://docs.microsoft.com/en-us/appcenter?WT.mc_id=appcenterdata-devto-mijam"&gt;App Center&lt;/a&gt;, which takes it from a DevOps focus to a fully-fledged Mobile Backend as a Service (MBaaS) solution. The first post was a little light on technical details as it was written on an iPad whilst on vacation, so I wanted to follow up with a little more meat. In this blog post, I’ll be showing how I’ve built a no-code backend to power a mobile app built with &lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/release-notes/4.0/4.0.0-sr2?WT.mc_id=appcenterdata-devto-mijam"&gt;Xamarin.Forms 4.0&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  App Center Data
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/appcenter?WT.mc_id=appcenterdata-devto-mijam"&gt;App Center&lt;/a&gt; data allows us to quickly add data functionality to our mobile apps, providing us to ability to manage, persist and sync data across app installations. It’s backed by the incredible &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction?WT.mc_id=appcenterdata-devto-mijam"&gt;Azure Cosmos DB&lt;/a&gt;, which is Microsoft’s globally distributed, low latency, highly-available cloud born database. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zsShcqVx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-13.40.20.png%3Fresize%3D750%252C519%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zsShcqVx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-13.40.20.png%3Fresize%3D750%252C519%26ssl%3D1" alt="Cosmos DB overview tab in the Azure Portal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Through using Cosmos DB as the underlying technology powering App Center Data, it opens up a world of opportunity to integrate our app into other services in Azure, as well as offering us a clear path to migration, should we find App Center doesn’t fit our growing needs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Collections and Partitions
&lt;/h3&gt;

&lt;p&gt;In order for Cosmos DB to meet our performance needs, we must partition our data into distinct subsets, called _logical partitions. _Logical partitions are formed based on the value of the _partition key _associated with each item found within the a collection. By default, App Center provides two partition keys within the SDK named &lt;code&gt;AppDocuments&lt;/code&gt; and &lt;code&gt;UserDocuments&lt;/code&gt;. These are defined in a Static Class named &lt;a href="https://github.com/microsoft/appcenter-sdk-dotnet/blob/36a5c54b06fba69d035d316bb5c14af3259c3efc/SDK/AppCenterData/Microsoft.AppCenter.Data.Shared/DefaultPartitions.cs#L9"&gt;DefaultPartitions&lt;/a&gt; which can be found within the AppCenter.Data namespace. Though we’re provided with two partitions to get started with, its not a requirement for us to use the built-in partition keys for all of our data. Instead, we are able to provide a string value for creating our own partition keys.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data?WT.mc_id=appcenterdata-devto-mijam"&gt;official Cosmos DB docs&lt;/a&gt; to learn more about data partitions. &lt;/p&gt;

&lt;h4&gt;
  
  
  AppDocuments – Read Only
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7sDrNPTB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-15%403x.png%3Fresize%3D224%252C216%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7sDrNPTB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-15%403x.png%3Fresize%3D224%252C216%26ssl%3D1" alt=""&gt;&lt;/a&gt;The &lt;code&gt;AppDocuments&lt;/code&gt;  partition is a read-only partition for storing data which can share the data across all users. Trying to write to the &lt;code&gt;AppDocuments&lt;/code&gt; partition will cause an exception to be thrown, so its best avoided! Instead, consider building auxiliary services to manage your &lt;code&gt;AppDocuments&lt;/code&gt;.  &lt;/p&gt;

&lt;h4&gt;
  
  
  UserDocuments – Read &amp;amp; Write
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e71_USHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-14%403x.png%3Fresize%3D193%252C243%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e71_USHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-14%403x.png%3Fresize%3D193%252C243%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;code&gt;UserDocuments&lt;/code&gt; are documents that are owned by an individual user and thus can only be read, updated and deleted by the owner . In order to enable &lt;code&gt;UserDocuments&lt;/code&gt;, you must have first configured App Center Authentication. With Authentication enabled, calling the CreateAsync method and providing the &lt;code&gt;UserDocuments&lt;/code&gt;partition key will set the partition key to currently signed in users Id. This will look something like: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“PartitionKey” :&lt;/strong&gt; “user-e831f9de-c35c-4139-ae9c-8b59b3fefc02”&lt;/p&gt;

&lt;h3&gt;
  
  
  Advocates App Data
&lt;/h3&gt;

&lt;p&gt;I wanted the demo app to demonstrate both &lt;code&gt;AppDocuments&lt;/code&gt; and &lt;code&gt;UserDocuments&lt;/code&gt;but initially couldn’t think of what data to show that should be read-only. After some consideration, I decided to utilise existing data from our &lt;a href="https://developer.microsoft.com/en-us/advocates/index.html"&gt;Cloud Advocate Directory&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I8nm5u6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-14.16.09.png%3Fresize%3D750%252C648%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I8nm5u6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-14.16.09.png%3Fresize%3D750%252C648%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This directory is a little like a right-of-passage for us Cloud Advocates, for every single one of us has had to write about ourselves when we joined the team. Most of the advocates have followed roughly the same format for their pages, which meant it was fairly easy (it not time consuming) to manually add my colleagues to the database. &lt;/p&gt;

&lt;h4&gt;
  
  
  Defining a Data Model
&lt;/h4&gt;

&lt;p&gt;Below I’ve defined the Advocate model which inherits from a BaseModel. The BaseModel class in extremely simple, with only 1 public property for the ID. The App Center SDK &lt;a href="https://docs.microsoft.com/en-us/appcenter/sdk/data/xamarin#defining-a-model?WT.mc_id=appcenter_data-personalblog-mijam"&gt;requires that all objects contain an ID&lt;/a&gt; of type string, so inheriting from the BaseModel ensures that every model is compatible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Advocate : BaseModel  
{  
public string Name { get; set; }  
public string GithubHandle { get; set; }  
    public string TwitterHandle { get; set; }  
    public string AvatarUrl { get; set; }  
    public string Bio { get; set; }  
    public List\&amp;lt;string\&amp;gt; Skills { get; set; }  
    //Used for location &amp;amp; timezone lookup  
public double Latitude { get; set; }  
public double Longitude { get; set; }  
 public List\&amp;lt;IgniteStop\&amp;gt; IgniteStops { get; set; }  

public Advocate()  
{  
Skills = new List\&amp;lt;string\&amp;gt;();  
 IgniteStops = new List\&amp;lt;IgniteStop\&amp;gt;();  
}  
 public string ClassType { get; set; }}  

public class IgniteStop  
{  
public string Name { get; set; }  
public string Image { get; set; }  
}  

//Base Model must have an ID Property of type string  
public class BaseModel  
{  
public BaseModel()  
    {  
     Id = Guid.NewGuid().ToString();  
    }  

public string Id { get; set; }  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You’ll note that I’ve added a &lt;code&gt;ClassType&lt;/code&gt; property, which I later set when saving the object. I added this to make my life easier when attempting to read all data from a partition, which is not of the same type. &lt;/p&gt;

&lt;p&gt;As previously mentioned, it’s not possible to create documents with the &lt;code&gt;AppDocuments&lt;/code&gt; partition key, so that rules out creating these documents using the &lt;a href="https://www.nuget.org/packages/Microsoft.AppCenter.Data?WT.mc_id=appcenterdata-devto-mijam"&gt;Xamarin SDK&lt;/a&gt;. Instead, I created dummy data manually and uploaded these manually to &lt;a href="https://azure.microsoft.com/en-us/updates/documentdb-data-explorer-preview-now-available-in-the-azure-portal?WT.mc_id=appcenterdata-devto-mijam"&gt;Cosmos DB using the Azure Portal&lt;/a&gt;. The first piece of dummy data was my own info, as shown below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hu2ca2JB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-14.20.24.png%3Fresize%3D750%252C777%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hu2ca2JB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-18-at-14.20.24.png%3Fresize%3D750%252C777%26ssl%3D1" alt="Visual Studio Code display JSON schema from Cosmos DB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Reading App Data with the Xamarin SDK
&lt;/h4&gt;

&lt;p&gt;Before we jump into looking at the &lt;a href="https://www.nuget.org/packages/Microsoft.AppCenter.Data?WT.mc_id=appcenterdata-devto-mijam"&gt;App Center Xamarin SDK&lt;/a&gt;, its worth noting that this sample uses an extremely popular Mvvm framework called &lt;a href="https://prismlibrary.github.io/"&gt;Prism.&lt;/a&gt; Prism is a rather opinionated framework which dictates that we should register services within the &lt;code&gt;App.cs&lt;/code&gt; of our &lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/release-notes/4.0/4.0.0-sr2?WT.mc_id=appcenterdata-devto-mijam"&gt;Xamarin.Forms&lt;/a&gt; Application for later use throughout our app. Normally for a demo, I’d put my data access code directly in the ViewModel, but given I’m trying embrace Prism, I thought I’d follow the recommended architecture and move this functionality into a separate service classes. Below is the incredibly simple ‘&lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App/blob/c40d84c8a5052c8c9e52b1daf665072fffa0839a/dotNET/Advocates/Services/AdvocatesDataService.cs#L11"&gt;AdvocatesDataService&lt;/a&gt;‘ class, which contains just one Method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AdvocatesDataService  
{  
public async Task\&amp;lt;IEnumerable\&amp;lt;Advocate\&amp;gt;\&amp;gt; GetAdvcoates()  
{  
try  
{  
var result = await Data.ListAsync\&amp;lt;Advocate\&amp;gt;(DefaultPartitions.AppDocuments);  
var unsorted = result.CurrentPage.Items.Select(a =\&amp;gt; a.DeserializedValue).Where(x =\&amp;gt; x.ClassType == "Advocate");  
 return new List\&amp;lt;Advocate\&amp;gt;(unsorted.OrderBy(x =\&amp;gt; x.Name));  
 }  
catch(Exception ex)  
{  
Crashes.TrackError(ex, null);  
return new List\&amp;lt;Advocate\&amp;gt;();  
}     }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Pagination
&lt;/h5&gt;

&lt;p&gt;As you may have seen, the above response is actually paginated, though I only handle the first page right now. This works at the moment because I’ve not added all of my colleagues to the database! As I get around to adding more of my colleagues, I’ll likely want to handle pagination properly.  &lt;code&gt;PaginatedDocuments&lt;/code&gt; have the following methods and properties: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HasNextPage&lt;/code&gt; : Boolean property indicating wether an extra page is available or not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CurrentPage&lt;/code&gt; : Property that returns the current page with type being &lt;code&gt;Page&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetNextPageAsync()&lt;/code&gt; : Method that asynchronously fetches the next page (the method returns an object of type &lt;code&gt;Task&amp;lt;Page&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;IEnumerator&amp;lt;DocumentWrapper&amp;gt;&lt;span&gt; &lt;/span&gt;&lt;code&gt;GetEnumerator()&lt;/code&gt;&lt;span&gt; &lt;/span&gt;: This is an enumerator for the paginated docs, which can traverse them&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;App Center doesn’t currently support offline persistence when listing documents.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5&gt;
  
  
  Service Registration with Prism
&lt;/h5&gt;

&lt;p&gt;I register this service within the &lt;code&gt;App.cs&lt;/code&gt; &lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App/blob/c40d84c8a5052c8c9e52b1daf665072fffa0839a/dotNET/Advocates/App.xaml.cs#L59"&gt;RegisterTypes&lt;/a&gt; method so that it can be used throughout my App.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;tabbedpage&amp;gt;&amp;lt;span style="font-family: Menlo;"&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;&amp;lt;span style="color: #009695;"&amp;gt;protected&amp;lt;/span&amp;gt; &amp;lt;span style="color: #009695;"&amp;gt;override&amp;lt;/span&amp;gt; &amp;lt;span style="color: #009695;"&amp;gt;void&amp;lt;/span&amp;gt; RegisterTypes(&amp;lt;span style="color: #3363a4;"&amp;gt;IContainerRegistry&amp;lt;/span&amp;gt; containerRegistry)&amp;lt;br&amp;gt;{&amp;lt;br&amp;gt; containerRegistry&amp;lt;/span&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;Register&amp;lt;/span&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style="color: #009695;"&amp;gt;typeof&amp;lt;/span&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style="color: #3363a4;"&amp;gt;AdvocatesDataService&amp;lt;/span&amp;gt;&amp;lt;span style="color: #222222;"&amp;gt;));&amp;lt;br&amp;gt;&amp;lt;br&amp;gt; //And a whole lot more...&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;}&amp;lt;/tabbedpage&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Below shows how to consume the now registered &lt;code&gt;AdvocateDataService&lt;/code&gt; from within your ViewModels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//ViewModel Constructor  
public AdvocatesPageViewModel(INavigationService navigationService,   
AdvocatesDataService advocatesDataService)  
{  
this.navigationService = navigationService;  
this.advoatesDataService = advocatesDataService;  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Calling the &lt;code&gt;GetAdvocates&lt;/code&gt; Method of the AdvocatesDataService class allows us to bind the results to a Xamarin.Forms TableView as seen below:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W46imGXv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-2%402x.png%3Fresize%3D461%252C430%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W46imGXv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Group-2%402x.png%3Fresize%3D461%252C430%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating &amp;amp; Reading User Data
&lt;/h4&gt;

&lt;p&gt;Now we’ve seen how we can use the Xamarin SDK to read lists of &lt;code&gt;AppDocuments&lt;/code&gt;, let’s take a look at how we can create, update, delete and read &lt;code&gt;UserDocuments&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To demonstrate &lt;code&gt;UserDocuments&lt;/code&gt;, I decided to add the ability to record what links we’ve shared with the community. The reason for recording this is because we (Microsoft Cloud Advocates) are measured on the number of users we direct to the Azure documentation. We measure this using Tracking Links which look a little like this: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;"https://docs.microsoft.com/appcenter?WT.mc_id=app-center-mbaas-personalblog-mijam"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The tracking element has been bolded to make it easier to see. &lt;/p&gt;

&lt;h5&gt;
  
  
  Defining a Data Model
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class TrackingLink : BaseModel  
{  
public string Url { get; set; }  
public string Event { get; set; }  
    public string Channel { get; set; }  
    public string Alias { get; set; }  
    public DateTime CreatedAt { get; set; }  
    public string ShareableLink { get; set; }  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The TrackingLink data model like the Advocate model inherits from BaseModel in order to ensure that it has a Id property string. &lt;/p&gt;

&lt;h5&gt;
  
  
  Tracking Link Data Service
&lt;/h5&gt;

&lt;p&gt;Having defined the data model, I set about implementing a &lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App/blob/c40d84c8a5052c8c9e52b1daf665072fffa0839a/dotNET/Advocates/Services/TrackingLinkDataService.cs#L13"&gt;TrackingLinkDataService&lt;/a&gt; class, which like our &lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App/blob/c40d84c8a5052c8c9e52b1daf665072fffa0839a/dotNET/Advocates/Services/AdvocatesDataService.cs#L11"&gt;AdvocateDataService&lt;/a&gt; class would be responsible for interacting with App Center. &lt;/p&gt;

&lt;h6&gt;
  
  
  Read All
&lt;/h6&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task\&amp;lt;IEnumerable\&amp;lt;TrackingLink\&amp;gt;\&amp;gt; GetTrackingLinks()  
{  
try  
{  
var result = await Data.ListAsync\&amp;lt;TrackingLink\&amp;gt;(DefaultPartitions.UserDocuments);  
var unsorted = result.CurrentPage.Items.Select(a =\&amp;gt; a.DeserializedValue).Where(x =\&amp;gt; x.ClassType == "TrackingLink");  

 return new List\&amp;lt;TrackingLink\&amp;gt;(unsorted.OrderBy(x =\&amp;gt; x.CreatedAt));  
}  
catch (Exception ex)  
{  
Crashes.TrackError(ex, null);  
return new List\&amp;lt;TrackingLink\&amp;gt;();     }  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Starting with &lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App/blob/c40d84c8a5052c8c9e52b1daf665072fffa0839a/dotNET/Advocates/Services/TrackingLinkDataService.cs#L15"&gt;GetTrackingLinks&lt;/a&gt;, this method fetches all the tracking links owned by the currently signed in user. Thankfully the App Center SDK deals with ensuring the correct data is returned so we don’t even need to specify the User ID in our method call.  &lt;/p&gt;

&lt;h6&gt;
  
  
  Create Link
&lt;/h6&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task\&amp;lt;bool\&amp;gt; SaveTrackingLink(TrackingLink trackingLink)  
{  
trackingLink.CreatedAt = DateTime.Now;    trackingLink.ClassType = "TrackingLink";  
 trackingLink.Alias = Xamarin.Essentials.Preferences.Get("Alias", "");  

 try  
{  
await Data.CreateAsync(trackingLink.Id.ToString(), trackingLink, DefaultPartitions.UserDocuments, new WriteOptions(TimeToLive.Infinite));  
return true;  
}  
catch(Exception ex)  
{  
Crashes.TrackError(ex, null);  
return false;  
}  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When saving a tracking link, I add a few extra properties such as the current DateTime, set the ClassType and then fetch the Alias using &lt;a href="https://docs.microsoft.com/en-us/xamarin/essentials?WT.mc_id=appcenter_data-personalblog-mijam"&gt;Xamarin.Essentials&lt;/a&gt;. Adding the optional WriteOptions means that our document will be stored locally if the user is offline, then will be persisted to the cloud as soon as the device regain connectivity. &lt;code&gt;TimeToLive.Infinite&lt;/code&gt; causes our tracking links object to be cached indefinitely rather than the default one day if not online. &lt;/p&gt;

&lt;h6&gt;
  
  
  Cosmos DB Document
&lt;/h6&gt;

&lt;p&gt;Creating a Tracking Link with the SDK creates a JSON document in &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction?WT.mc_id=appcenterdata-devto-mijam"&gt;Cosmos DB&lt;/a&gt; that looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ "document": { "CreatedAt": "2019-06-10T15:42:34.739151+01:00", "Id": "9a0f4e0e-545f-473e-ac6c-f44c2581c93a", "ClassType": "TrackingLink", "Alias": "Mijam", "Url": "https://test.co.uk", "Event": "Event", "Channel": "Channel", "ShareableLink": "https://test.co.uk?WT.mc\_id=Event-Channel-" }, "PartitionKey": "user-e831f9de-c35c-4039-ae9c-8b59b0fefc02", "id": "9a0f4e0e-545f-473e-ac6c-f44c2581c93a", "\_rid": "BcpnAIigIFdsAAAAAAAAAA==", "\_self": "dbs/BcpnAA==/colls/BcpnAIigIFc=/docs/BcpnAIigIFdsAAAAAAAAAA==/", "\_etag": "\"0000584b-0000-1100-0000-5cfe6c970000\"", "\_attachments": "attachments/", "\_ts": 1560177815 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The important thing to note is the PartitionKey as this relates to the UserId which is returned as part of the authentication process.&lt;/p&gt;

&lt;h6&gt;
  
  
  Deleting Links
&lt;/h6&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task\&amp;lt;bool\&amp;gt; DeleteTrackingLink(TrackingLink trackingLink)  
{  
try  
{  
await Data.DeleteAsync\&amp;lt;TrackingLink\&amp;gt;(trackingLink.Id, DefaultPartitions.UserDocuments);  
return true;  
 }  
 catch (Exception ex)  
 {  
Crashes.TrackError(ex, null);  
return false;  
}  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Deleting data is very straight forward using the DeleteAsync method, which covers the basics of CRUD operations using the App Center SDK. &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In this post I’ve explained how I’ve used the new preview features of &lt;a href="https://docs.microsoft.com/en-us/appcenter?WT.mc_id=appcenter_data-personalblog-mijam"&gt;Visual Studio App Center&lt;/a&gt; to build a &lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/release-notes/4.0/4.0.0-sr2?WT.mc_id=appcenterdata-devto-mijam"&gt;Xamarin.Forms 4.0&lt;/a&gt; app that also uses &lt;a href="https://prismlibrary.github.io"&gt;Prism&lt;/a&gt;. You can grab the entire project from &lt;a href="https://github.com/MikeCodesDotNET/Microsoft-Cloud-Advocates-App"&gt;my Github! &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hopefully by this point you’ve seen just how easy it is to get started with &lt;a href="https://www.nuget.org/packages/Microsoft.AppCenter.Data?WT.mc_id=appcenterdata-devto-mijam"&gt;App Center Data&lt;/a&gt;.  Its a very un-opinionated SDK, with no requirements on how you define your schema, which makes it a perfect fit for developers who find traditional SQL database too rigid and inflexible. &lt;/p&gt;

&lt;p&gt;If you want to learn more about App Center Data then check out the &lt;a href="https://docs.microsoft.com/en-us/appcenter/sdk/"&gt;rich documentation&lt;/a&gt; on over at the Microsoft Docs Portal.&lt;/p&gt;

</description>
      <category>visualstudioappcenter</category>
      <category>azure</category>
      <category>logicapps</category>
      <category>mbaas</category>
    </item>
    <item>
      <title>Getting started with Data and Auth using Microsoft App Center</title>
      <dc:creator>Mike James</dc:creator>
      <pubDate>Mon, 10 Jun 2019 09:30:42 +0000</pubDate>
      <link>https://dev.to/mikecodesdotnet/getting-started-with-data-and-auth-using-microsoft-app-center-26lm</link>
      <guid>https://dev.to/mikecodesdotnet/getting-started-with-data-and-auth-using-microsoft-app-center-26lm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7f_2Q9Ge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-10-at-08.56.05.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7f_2Q9Ge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-10-at-08.56.05.png%3Fw%3D750%26ssl%3D1" alt="Screenshot 2019-06-10 at 08.56.05.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my first week working for &lt;a href="https://docs.microsoft.com/en-us/xamarin/?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Xamarin&lt;/a&gt;, I was flown to Austin Texas from London in order to help support Xamarin Evolve 2013. Like most conferences, we had sponsors, which included a little startup called Parse. Parse was a backend born in 2011 that allowed mobile developers to easily add cloud storage, push notifications and authentication to their apps. I was sold on the technology immediately and got started building out sample apps to demo Xamarin using parse backends.&lt;/p&gt;

&lt;p&gt;Parse was acquired by Facebook in 2013 and lasted until 2016 before being shut down. Thankfully Facebook made Parse open-source which allowed users to migrate their Parse backends to cloud providers such as Azure with our &lt;a href="https://azuremarketplace.microsoft.com/en-us/marketplace/apps/Microsoft.ParseServer?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Parse Server template.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Parse no longer having a maintainer was a problem for lots of users, who would want to bet new apps on unmaintained services?  I decided that any new apps I developed would not rely on Parse but instead I’d need to find an alternative. Being a .NET Developer, it made sense to use Microsoft’s &lt;a href="https://docs.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-value-prop?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Azure Mobile App service&lt;/a&gt;, which consists of a .NET Framework based web API project and a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/overview/azure/mobileapps/client?view=azure-dotnet"&gt;client SDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Embracing Azure Mobile Apps saw me spending more time in Visual Studio writing generic Web APIs and broadening my experience with Web API development. These skills provided me the ability to drop the pre-built solutions and start rolling my own as seen in the &lt;a href="https://github.com/microsoft/app-innovation-workshop"&gt;Mobile Cloud Workshop&lt;/a&gt; I created with my esteemed colleague, Robin-Manuel.&lt;/p&gt;

&lt;p&gt;Whilst rolling the backend offers unparalleled flexibility, it’s also no small undertaking to develop, test and maintain, which was ultimately a distraction from my core goal of building a mobile app. I’ve not reached the levels of productivity developing cloud connected apps since migrating from Parse in 2016.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Center
&lt;/h2&gt;

&lt;p&gt;This has all changed now with the latest update to Microsoft &lt;a href="https://visualstudio.microsoft.com/app-center/?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;App Center&lt;/a&gt;. If you’ve not heard of App Center, it’s the replacement to HockeyApp or Xamarin Insights. It’s our automated build, test and analytics platform, designed specifically for mobile developers.&lt;/p&gt;

&lt;p&gt;App Center has proved invaluable for building better apps but it wasn’t a ‘one stop shop’ for mobile dev, with me having to roll my own backends for data and authentication. This changed earlier this year at Build, with the addition of authentication and data storage features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lLw6ZeSg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-05-23-at-12.24.18.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lLw6ZeSg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-05-23-at-12.24.18.png%3Fw%3D750%26ssl%3D1" alt="Screenshot 2019-05-23 at 12.24.18.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Authentication is one of those features that I like to avoid as its unexciting and easy to get wrong. It’s this reason that I never roll my own authentication solution, but instead rely on 3&lt;sup&gt;rd&lt;/sup&gt; parties like &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-overview?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Active Directory&lt;/a&gt; or &lt;a href="https://auth0.com/"&gt;Auth0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I first started using Azure Mobile Apps with its companion mobile SDK, I was able to authenticate users with only a couple of lines of code, which made it a no brainer to add to my demos. I’m super happy to say that the new Mobile Apps SDK makes it just as easy! It does this by wrapping the &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-overview?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Microsoft Authentication Library&lt;/a&gt; (MSAL) which implements authentication using OAuth 2.0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vtqkooRW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/token-exchange-service.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vtqkooRW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/token-exchange-service.png%3Fw%3D750%26ssl%3D1" alt="token-exchange-service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The authentication process is powered by &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-overview?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Active Directory B2C&lt;/a&gt; (Business to Consumer), which makes it’s incredibly easy to setup! It also makes it possible to use a huge variety of identity providers such as Google, Twitter, Facebook and Microsoft as well as integrate with 3rd party providers. It gets all of the standard B2C functionality, such as using machine learning to detect suspicious behaviour and options for multi-factor auth.&lt;/p&gt;

&lt;p&gt;Once a user has authenticated, they can create documents using App Center Data which are only visible to them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3av5i9oO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-05-31-at-17.26.37.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3av5i9oO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-05-31-at-17.26.37.png%3Fw%3D750%26ssl%3D1" alt="Screenshot 2019-05-31 at 17.26.37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The biggest difference between App Center and Azure Mobile Apps has to be how we model and&lt;a href="https://docs.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-offline-data-sync?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;store data.&lt;/a&gt;) With the older Azure Mobile Apps, we could pick between Microsoft Azure SQL or for testing, a SQLite Database. The only option we had was to a relational database, which was great if you had a schema that lends itself well to being normalised.&lt;/p&gt;

&lt;p&gt;App Center uses &lt;a href="https://azure.microsoft.com/en-us/services/cosmos-db/?WT.mc_id=appcentermbaasintro-devto-mijam"&gt;Cosmos DB&lt;/a&gt; as its underlying data storage service. This is our cloud-first, global scale NoSQL database offering. Cosmos DB allows us to forget about database scaling as it promises low latency and high availability in all the regions you deploy your data to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9PCQuYyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/data-architecture.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9PCQuYyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/data-architecture.png%3Fw%3D750%26ssl%3D1" alt="data-architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Partitioning Data
&lt;/h3&gt;

&lt;p&gt;App Center only uses one collection which helps keeps cost down as we pay for every collection, even if empty when using Cosmos DB. Within the single collection used for App Center, you can define two types of document, private and public.&lt;/p&gt;

&lt;p&gt;Private documents consist of user data,  allowing authenticated users to have read and write access to edit the contents.&lt;/p&gt;

&lt;p&gt;Public documents only allow for read access (using the App Center SDK) as to avoid users being able to overwrite global data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rlXH3trp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/data-partitions.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rlXH3trp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/mikecodes.net/wp-content/uploads/2019/06/data-partitions.png%3Fw%3D750%26ssl%3D1" alt="data-partitions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Offline
&lt;/h3&gt;

&lt;p&gt;One of my favourite features of using Azure Mobile Apps was its ability to support offline-synchronization of data between client and the backend. Offline sync not only allows apps to work offline but also makes them appear more performant when online.&lt;/p&gt;

&lt;p&gt;App Center supports offline read and writes but the data is only cached for a day by default. It’s possible to set a time-to-live (TTL) if required. If connectivity is lost, users will still have the ability to read cached documents and write data with changes cached until connectivity is restored. One important thing to note is that conflicts are handled using “last write wins”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema
&lt;/h3&gt;

&lt;p&gt;If I use the App Center Data SDK then I can use plain CLR objects with the only requirement that I have an ID property of type Guid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Guid Id { get; set; } = Guid.NewGuid();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When the object is actually saved to App Center, you’ll see that the schema is a little different to what you might expect. This is because App Centner add a few extra properties and nests your schema into a object named “document”.&lt;/p&gt;

&lt;p&gt;This is very important to remember if you’re going to interact with the data using other services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JuDA5V2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-10-at-10.20.28.png%3Fw%3D750%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JuDA5V2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/mikecodes.net/wp-content/uploads/2019/06/Screenshot-2019-06-10-at-10.20.28.png%3Fw%3D750%26ssl%3D1" alt="Screenshot 2019-06-10 at 10.20.28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I’ve only just started to explore what I can build with App Center and how best to integrate it into my app development process.&lt;/p&gt;

&lt;p&gt;With less than a week of development, I’ve already got an app built which supports push notifications, offline sync of data and authentication. This kind of productivity is a huge win in terms of my ability to add features as I focus on the app and let the App Center team focus on the backend infrastructure.&lt;/p&gt;

&lt;p&gt;If you’ve ever used Parse, Firebase or Azure Mobile Apps then I highly recommend giving App Center a try.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>xamarinforms</category>
      <category>prism</category>
      <category>appcenter</category>
    </item>
  </channel>
</rss>
