<?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: James Montemagno</title>
    <description>The latest articles on DEV Community by James Montemagno (@jamesmontemagno).</description>
    <link>https://dev.to/jamesmontemagno</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%2F428154%2F46fa65df-835c-4d5c-aa53-23f403fb0b57.jpeg</url>
      <title>DEV Community: James Montemagno</title>
      <link>https://dev.to/jamesmontemagno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jamesmontemagno"/>
    <language>en</language>
    <item>
      <title>An Introduction to the World of Containers with .NET 8</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Fri, 16 Feb 2024 19:19:47 +0000</pubDate>
      <link>https://dev.to/dotnet/an-introduction-to-the-world-of-containers-with-net-8-4elf</link>
      <guid>https://dev.to/dotnet/an-introduction-to-the-world-of-containers-with-net-8-4elf</guid>
      <description>&lt;p&gt;Containers are a popular way of packaging and distributing applications in today’s Cloud Native landscape – but what are they, and how can .NET developers integrate them into their workflows? Today, let's talk about what containers are, how they relate to Docker, and how the .NET tooling makes it easy for developers to easily streamline the process of creating containers with .NET.&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers with .NET For Beginners
&lt;/h2&gt;

&lt;p&gt;Follow along with this blog and our new &lt;a href="https://dotnet.microsoft.com/learn/videos" rel="noopener noreferrer"&gt;Beginner's series&lt;/a&gt; on containers and Docker for .NET.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/HA8rpDWMRq0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Containers?
&lt;/h2&gt;

&lt;p&gt;A container is a standard unit of software that packages up code and all its dependencies. It allows applications to run consistently across different computing environments. You'll find containers supported by all major cloud providers with various ways to run your containers, ranging from serverless options to fully managed Kubernetes services.&lt;/p&gt;

&lt;p&gt;Containers provide a flexible choice for application packaging, making it a valuable skill to master. That's why .NET invests in making containers easy to use for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benefits of Containers
&lt;/h2&gt;

&lt;p&gt;So why should you use containers? The answer lies in a uniform deployment and uniform execution of applications. Containers make the job of maintaining and operating your services much easier in the long term. In addition, the whole world of automated DevOps, tooling, alerting, and monitoring can be integrated into your solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Setup
&lt;/h2&gt;

&lt;p&gt;The first step is to install the &lt;a href="https://dotnet.microsoft.com/dotnet" rel="noopener noreferrer"&gt;.NET SDK&lt;/a&gt;. You can use the .NET CLI to create containers which by default creates Linux containers. You can create these containers on any operating system; Windows, Mac, Linux, or the &lt;a href="https://learn.microsoft.com/windows/wsl/install" rel="noopener noreferrer"&gt;Windows Subsystem for Linux&lt;/a&gt;. The choice is yours however you enjoy developing. Additionally, having &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; installed will enable you to run your containers after you create them with the .NET SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Containers with .NET
&lt;/h2&gt;

&lt;p&gt;Now, let's take a look at just how easy it can be to create containers with .NET. To start, let's first create a new web app with the following .NET CLI command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet new web &lt;span class="nt"&gt;-o&lt;/span&gt; container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can navigate to the new directory that it was created in:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now run the application locally with &lt;code&gt;dotnet run&lt;/code&gt;, but let's go ahead and create a container by publishing the app with the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet publish &lt;span class="nt"&gt;-t&lt;/span&gt;:PublishContainer


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By running a single command, you can create a container of your web app. This is the same &lt;code&gt;publish&lt;/code&gt; command you're already familiar with for publishing your web application, but now it's being used for containerization. The .NET SDK will provide you with information about the container it just created, such as the container name, the tag, and the base image it chose.&lt;/p&gt;

&lt;p&gt;Speaking of the base image, it's like the operating system and software configuration that your application will be deployed onto. In this example, as a web app targeting .NET 8, the SDK chose an ASP.NET image from Microsoft with the 8.0 tag. You will see output from the command similar to the following that highlights this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

Building image &lt;span class="s1"&gt;'conainer-webapp'&lt;/span&gt; with tag &lt;span class="s1"&gt;'latest'&lt;/span&gt; on top of the base image &lt;span class="s1"&gt;'mcr.microsoft.com/dotnet/aspnet:8.0'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Pushed image &lt;span class="s1"&gt;'conainer-webapp:latest'&lt;/span&gt; to &lt;span class="nb"&gt;local &lt;/span&gt;registry via &lt;span class="s1"&gt;'docker'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To get a closer look at the image we just built, we can use Docker Desktop. It's fascinating to see how the image is composed of different layers, each representing a portion of the file system or a change to the operating environment. These layers come together to create a runnable container.&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%2Fo2y3fvpbglus147q1raz.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%2Fo2y3fvpbglus147q1raz.png" alt="Layer of the container in Docker Desktop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's run the container with a docker &lt;code&gt;run&lt;/code&gt; command that specifies the container name:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker run &lt;span class="nt"&gt;-P&lt;/span&gt; container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Optionally, we could run the container directly from Docker Desktop instead of using the command. If we open Docker Desktop, we can access our running application by clicking on the port link next to our container:&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%2Fwvstdf21hu1j3nnymz3d.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%2Fwvstdf21hu1j3nnymz3d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it, a browser will open up with our new web app running in a container!&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%2Fqpvk5jbo7018vfmavftd.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%2Fqpvk5jbo7018vfmavftd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps: Deep Dive into Tooling &amp;amp; Publishing to the cloud
&lt;/h2&gt;

&lt;p&gt;That wraps up our quick taste of containers and how .NET makes it easy to get started with them. This is only the first step, and I have a full beginner's series that dives deeper into the &lt;a href="https://www.youtube.com/watch?v=qCxSYymD0ug&amp;amp;list=PLdo4fOcmZ0oXss45l49Q8h-Omuwo2FD-U&amp;amp;index=2&amp;amp;pp=gAQBiAQB" rel="noopener noreferrer"&gt;tooling experiences available on the command line as well as in Visual Studio and Visual Studio Code&lt;/a&gt;. Then I go into how you can take your containers and &lt;a href="https://www.youtube.com/watch?v=21zduERRS3M&amp;amp;list=PLdo4fOcmZ0oXss45l49Q8h-Omuwo2FD-U&amp;amp;index=3&amp;amp;pp=gAQBiAQB" rel="noopener noreferrer"&gt;publish them to container registries&lt;/a&gt;. In addition, we have &lt;a href="https://aka.ms/learn-microservices" rel="noopener noreferrer"&gt;full training on Microsoft Learn&lt;/a&gt; for containers, microservices, and cloud-native development with .NET that I highly recommend you checkout.&lt;/p&gt;

&lt;p&gt;Thanks for joining me on this quick introduction to containers with .NET.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI-assisted content. This article was partially created with the help of AI. An author reviewed and revised the content as needed.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>docker</category>
      <category>aspnet</category>
    </item>
    <item>
      <title>Leveraging Existing Web Content to Build Hybrid Apps with .NET MAUI</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Fri, 04 Aug 2023 16:20:55 +0000</pubDate>
      <link>https://dev.to/dotnet/leveraging-existing-web-content-to-build-hybrid-apps-with-net-maui-48me</link>
      <guid>https://dev.to/dotnet/leveraging-existing-web-content-to-build-hybrid-apps-with-net-maui-48me</guid>
      <description>&lt;p&gt;Are you a web developer intrigued by the idea of building native mobile &amp;amp; desktop applications? If you've been developing with Angular, React, or even just HTML and JavaScript, there's good news for you! In this post, we'll explore how you can leverage your existing web content to build native iOS, Android, Mac, and Windows apps using .NET MAUI and the experimental &lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KAU9SLm1nn0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Reuse Web Content?
&lt;/h2&gt;

&lt;p&gt;Imagine being able to reuse all the goodness you've created with your chosen web frameworks in your native mobile apps. By leveraging your existing web development skills, you can save time and effort by not starting from scratch with native mobile development. Plus, you can bring the power of your web components, designs, and functionality to the native world.&lt;/p&gt;

&lt;p&gt;Additionally, building native apps with .NET MAUI enables you to access native APIs and controls, giving you the best of both worlds. You can mix and match UI components, create a seamless user experience, and even access platform-specific features. The possibilities are practically endless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing .NET MAUI
&lt;/h2&gt;

&lt;p&gt;.NET MAUI is a powerful framework that builds on top of .NET for iOS, Android, Mac, and Windows (WinUI3), allowing you to create native apps with a unified API. I provides a single robust framework to make cross-platform app development easier than ever before.&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%2F1185nqzbsoj7vv37tng9.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%2F1185nqzbsoj7vv37tng9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of the box, .NET MAUI enables you to use C# and XAML to build native UIs from shared code and access the underlying native APIs from C#. You have the flexibility to create apps that run on multiple platforms without sacrificing the performance and user experience provided by native controls and APIs.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DuNLR_NJv8U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Hybrid Apps with Blazor Hybrid
&lt;/h2&gt;

&lt;p&gt;If you're a Blazor developer, you're in luck! Blazor developers can easily reuse their Blazor components between their web applications and .NET MAUI applications. This powerful capability is included "in the box" which allows you to blend native and web UI components seamlessly.&lt;/p&gt;

&lt;p&gt;You can mix Blazor and native controls to create a unified and consistent user interface. This means you can build your UIs once and use them across different platforms, reducing development effort and ensuring a consistent user experience. The hybrid web view experiment offers great potential for Blazor developers looking to extend their apps to the native mobile world.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lqLfY9zNKNY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Hybrid Apps with HTML, JavaScript, Angular, or React
&lt;/h2&gt;

&lt;p&gt;.NET MAUI doesn't limit you to just Blazor. You can also leverage your skills in HTML, JavaScript, Angular, or React to build hybrid apps with .NET Maui. This is made possible by the introduction of the experimental &lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;, which enables you to incorporate web content into your native apps seamlessly.&lt;/p&gt;

&lt;p&gt;To get started, you'll need to add the &lt;code&gt;Ejl.MauiHybridWebView&lt;/code&gt; NuGet package to your MAUI app. This package provides all the necessary functionality for integrating web content. Once added, you can create your HTML, JavaScript, and CSS files to define the web user interface.&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%2F2lf5j4fhpt47yjocq11k.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%2F2lf5j4fhpt47yjocq11k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hybrid web view works by embedding a native web view control into your app, allowing it to display your web content using the platform's native rendering capabilities. This ensures a consistent look and feel across different platforms, while still giving you the freedom to use your preferred web technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take It Further - Full React Application
&lt;/h2&gt;

&lt;p&gt;If you want to take it a step further, you can even embed an entire React application within your .NET MAUI app. This is made possible by the flexibility and power of the HybridWebView to incorporate complex web applications into native apps seamlessly and communicate between JavaScript and C#.&lt;/p&gt;

&lt;p&gt;By embedding a React application, you can bring the full power of React's component-centric approach to your native app development. This allows you to create highly interactive and dynamic user interfaces, leveraging the extensive React ecosystem of libraries and components. All while access native APIs and business logic written in C#.&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%2Fnkvotuqrzu25n8aftrlb.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%2Fnkvotuqrzu25n8aftrlb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the capability to integrate web technology like React into your .NET MAUI apps, the possibilities for creating rich, engaging, and performant mobile experiences are virtually limitless.&lt;/p&gt;

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

&lt;p&gt;Building native apps doesn't have to mean starting from scratch. With .NET MAUI, you can leverage your existing web development skills and components to create powerful and feature-rich native apps. Whether you're using Blazor, Angular, React, or just HTML and JavaScript, .NET MAUI provides a unified platform to build cross-platform apps that deliver native performance and access to native features.&lt;/p&gt;

&lt;p&gt;So, why not explore the possibilities of reusing your existing web content with .NET MAUI? Start building your native mobile apps today and discover the countless opportunities to create amazing experiences for your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/dotnet/maui/" rel="noopener noreferrer"&gt;.NET MAUI official documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/Ejl.MauiHybridWebView" rel="noopener noreferrer"&gt;Ejl.Maui.HybridWebView NuGet package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was partially created with the help of AI. James reviewed and revised the content as needed.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>blazor</category>
      <category>aspnetcore</category>
      <category>dotnetmaui</category>
    </item>
    <item>
      <title>Let's Learn .NET - Blazor Hybrid - July 28th 2022 - Free Live Stream Event</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Wed, 27 Jul 2022 17:44:00 +0000</pubDate>
      <link>https://dev.to/dotnet/lets-learn-net-blazor-hybrid-july-28th-2022-free-live-stream-event-2gad</link>
      <guid>https://dev.to/dotnet/lets-learn-net-blazor-hybrid-july-28th-2022-free-live-stream-event-2gad</guid>
      <description>&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walks through the fundamentals of using C# and .NET. This month, we are looking at Blazor Hybrid and how to use it to &lt;strong&gt;build hybrid apps for desktop and mobile with .NET MAUI completely in C# using modern web technologies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In a Blazor Hybrid app, Razor components run natively on the device. Components render to an embedded Web View control through a local interop channel. Components don't run in the browser, and WebAssembly isn't involved. Razor components load and execute code quickly, and components have full access to the native capabilities of the device through the .NET platform. Join us as we explore Blazor Hybrid together!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/iI058EA_maE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Thursday, July 28th at 8:30 AM - 10:30 AM Pacific&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt; or on &lt;a href="https://www.youtube.com/watch?v=iI058EA_maE"&gt;YouTube&lt;/a&gt;. Sign-in, ask questions, and learn how to start building accessible apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introductions (5 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meet the team!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals (20 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazor Hybrid 101 

&lt;ul&gt;
&lt;li&gt;What is Blazor? &lt;/li&gt;
&lt;li&gt;What is Blazor Hybrid&lt;/li&gt;
&lt;li&gt;What is .NET MAUI&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pre-requisites &amp;amp; installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop (60 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/modules/build-blazor-hybrid/?WT.mc_id=friends-0000-jamont"&gt;Build a mobile &amp;amp; desktop app with Blazor Hybrid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.theurlist.com/letslearndotnet-blazor-hybrid"&gt;Blazor resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dot.net/videos"&gt;.NET 101 Videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>blazor</category>
      <category>dotnetmaui</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Open-source .NET MAUI Workshop - Multi-platform apps with C#</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Wed, 30 Mar 2022 16:25:00 +0000</pubDate>
      <link>https://dev.to/dotnet/open-source-net-maui-workshop-multi-platform-apps-with-c-nle</link>
      <guid>https://dev.to/dotnet/open-source-net-maui-workshop-multi-platform-apps-with-c-nle</guid>
      <description>&lt;p&gt;The .NET Foundation helps organize "&lt;a href="https://dotnetfoundation.org/community/resources" rel="noopener noreferrer"&gt;Presentations in a Box&lt;/a&gt;" including workshops, demos, presentations, eBooks, and a lot more from the .NET team and the .NET community. In recent months, the ASP.NET Core Beginners, Blazor, and C# workshops have been fully updated to .NET 6 and C# 10! If you are looking to learn or teach .NET and C#, these are great resources to start at.&lt;/p&gt;

&lt;p&gt;Personally, I contributed the Xamarin.Forms workshop to the .NET Foundation resources, and with .NET MAUI around the corner, I thought it was time to update this workshop to the latest and greatest tech. So, today, I am pleased to announce the launch of the &lt;a href="https://github.com/dotnet-presentations/dotnet-maui-workshop" rel="noopener noreferrer"&gt;.NET MAUI workshop&lt;/a&gt; available right now today! This full day workshop walks through everything .NET MAUI and has you building a full application from scratch that grabs and displays information from web API, navigates to details, and adds native platform features.&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%2Fysrccfwffk3gmaasumyp.gif" 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%2Fysrccfwffk3gmaasumyp.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a full outline of the workshop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 0 - 30 Min Session - Introduction to .NET MAUI Session &amp;amp; Setup Help&lt;/li&gt;
&lt;li&gt;Part 1 - Single Page List of Data&lt;/li&gt;
&lt;li&gt;Part 2 - MVVM &amp;amp; Data Binding&lt;/li&gt;
&lt;li&gt;Part 3 - Navigation&lt;/li&gt;
&lt;li&gt;Part 4 - Implementing Platform Features&lt;/li&gt;
&lt;li&gt;Part 5 - CollectionView &amp;amp; Beyond&lt;/li&gt;
&lt;li&gt;Part 6 - Theming the app &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a slide deck presentation for each part of the workshop alongside a full readme walkthrough of completing the exercise. I am super excited to release this and I am super open to feedback as well. I am presenting this at a few upcoming conferences and then plan to do a full recording on my &lt;a href="https://youtube.com/jamesmontemagno" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnetmaui</category>
      <category>csharp</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Implementing In-App Subscriptions in iOS &amp; Android with no backend servers</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Mon, 07 Feb 2022 21:00:17 +0000</pubDate>
      <link>https://dev.to/dotnet/implementing-in-app-subscriptions-in-ios-android-with-no-backend-servers-1pgm</link>
      <guid>https://dev.to/dotnet/implementing-in-app-subscriptions-in-ios-android-with-no-backend-servers-1pgm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j7jmPbVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/en-lockup-hero-large.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j7jmPbVA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/en-lockup-hero-large.png" alt="Implementing In-App Subscriptions in iOS &amp;amp; Android with no backend servers" width="830" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the years I have &lt;a href="https://montemagno.com/my-apps/"&gt;created several apps&lt;/a&gt; that I am super proud of, and for the most part, I have always put them out for free onto the app stores. More recently I have been experimenting with different monetization strategies for the apps so users can unlock features or just leave a tip. For the longest time I kept things simple with a "non-consumable" one-time purchase. The strategy is straight forward, they either purchased the item or they didn't. Based on this information you would unlock the features in the app. My nifty &lt;a href="https://github.com/jamesmontemagno/InAppBillingPlugin"&gt;InAppBilling .NET plugin&lt;/a&gt; for iOS, Android, macOS, and Windows comes in super handy and makes it just a few lines of code to implement this logic. Over the holiday break I decided to take things a step further and dip my toes into the world of subscriptions, and what I found left my code in a complete state of madness! Before I go into details on how I decided to implement subscriptions, I recommend listening to our recent &lt;a href="https://www.mergeconflict.fm/"&gt;Merge Conflict&lt;/a&gt; episode all about subscriptions!&lt;/p&gt;

&lt;p&gt;One of my goals of this was to not use any backend servers or accounts at all as I didn't want to add additional costs to management. That leads to even more complexity, but for me it was worth it, so let's get into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up subscriptions
&lt;/h2&gt;

&lt;p&gt;The first thing that you are going to need to do is setup your subscriptions in the App Store and Google Play. Each store has the concept of "Groups" that have multiple subscription options in them that users can upgrade/downgrade from. I am just offering a single subscription to keep things simple. The settings are straight forward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How long is a subscription (1 week, 1 month, 2 months, 3 months, 6 months, 1 year)&lt;/li&gt;
&lt;li&gt;How much is the subscription (as low as 0.49)&lt;/li&gt;
&lt;li&gt;Name, Description, and Product ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important you select the correct subscription length as you can't change this after it is approved. Additionally, you should set a unique Product ID across your apps and try to name them the same between iOS and Android for simplicity later. You can change the price later if you desire, but note that lowering it will affect all users, but if you increase you have the option to make it for all users or just for new subscriptions. I prefer to make it a bit higher to start and then adjust later as needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/app-store/subscriptions/"&gt;Apple&lt;/a&gt; and &lt;a href="https://developer.android.com/google/play/billing/subscriptions"&gt;Google&lt;/a&gt; have great documentation if you need more information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Purchasing subscriptions
&lt;/h2&gt;

&lt;p&gt;Now that we have setup the subscription information, we can start our implementation. I mean technically you could skip the step ahead as well if you haven't prepped the app store yet, but of course you won't be able to test out things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--37tKKeCE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--37tKKeCE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-1.png" alt="Implementing In-App Subscriptions in iOS &amp;amp; Android with no backend servers" width="410" height="532"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Purchase screen for subscription&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Purchasing is straight forward, and for this blog I am going to use my InAppBilling plugin that under the hood uses &lt;a href="https://developer.apple.com/documentation/storekit"&gt;StoreKit&lt;/a&gt; and the Android &lt;a href="https://developer.android.com/google/play/billing"&gt;Billing Library&lt;/a&gt;. Making the purchase is the same as any other purchase using the SDK, but the information that is returned is the most important part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;PurchaseSubscription&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsBusy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;IsBusy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// check internet first with Essentials&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Connectivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NetworkAccess&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;NetworkAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Internet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            

        &lt;span class="c1"&gt;// connect to the app store api&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConnectAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&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;productIdSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mysubscriptionid"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;//try to make purchase, this will return a purchase, empty, or throw an exception&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PurchaseAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;productIdSub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ItemType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//nothing was purchased&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;PurchaseState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Purchased&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubExpirationDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSubTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPurchasedSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// Update UI if necessary if they have &lt;/span&gt;
            &lt;span class="nf"&gt;SetPro&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;try&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// It is required to acknowledge the purchase, else it will be refunded&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DevicePlatform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcknowledgePurchaseAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PurchaseToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to acknowledge purcahse: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InAppBillingPurchaseException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PurchaseError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GeneralError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InAppBillingPurchaseException&lt;/span&gt; &lt;span class="n"&gt;purchaseEx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle all the different error codes that can occure and do a pop up&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle a generic exception as something really went wrong&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DisconnectAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;IsBusy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&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;p&gt;This looks like a lot of code, but it is only four calls to the billing service itself: Connect, buy, acknowledge (on Android), disconnect. And funny enough, on iOS you don't even need to really connect or disconnect as it doesn't do anything.&lt;/p&gt;

&lt;p&gt;Now, the real thing to pay attention to is what we do when the user makes a successful purchase. I store 3 values that I store in preferences using Essentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;   &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubExpirationDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSubTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPurchasedSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SubExpirationDate&lt;/strong&gt; : This value lets me check if the subscription is still valid and when to refresh the subscription status next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HasPurchasedSub&lt;/strong&gt; : A simple value to determine if they have EVER purchased a subscription. Just valuable information that I will use later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CheckSubStatus&lt;/strong&gt; : This value I use to determine if I have prompted the user to refresh the subscription status, it is true if the subscription is valid, and I have never prompted them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That &lt;strong&gt;AddSubTime&lt;/strong&gt; is a nice little extension method I made throughout my app to make it easier when checking if subscriptions are valid or not.&lt;br&gt;
&lt;/p&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;static&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nf"&gt;AddSubTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMonths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AddDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I decided to add not only a month, but also five extra days just in case there is some weird billing issue. I figure what an extra five days anyway.&lt;/p&gt;

&lt;p&gt;Now throughout my app I can run a single check to see if they have purchased a subscription and if it is valid:&lt;br&gt;
&lt;/p&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;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsSubValid&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HasPurchasedSub&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SubExpirationDate&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling subscription renewals and cancelations
&lt;/h2&gt;

&lt;p&gt;At this point, the user now has access to the subscription for a full month (and 5 days)! What happens when it is time to refresh that subscription status? I went with a simple approach on launch of the application that notifies the user that the subscription status needs to be refreshed. I could do this in the background, but I made it very transparent to the users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPurchasedSub&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSubValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Subcription Status Refresh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Looks like it is time to update your subscription status. If you canceled and resumed, you can always refresh your status on the settings page by restoring purchases."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Refresh status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Maybe Later"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Connectivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NetworkAccess&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;NetworkAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Internet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"No internet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Please check internet connection and try restore purchases again in settings."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;//refresh status here&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RestorePurchases&lt;/span&gt;&lt;span class="p"&gt;();&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;p&gt;Here, I check to see if they ever purchased a subscription, if it is no longer valid, and if I should check the subcription status with a prompt. If they want to refresh the status, I call the &lt;code&gt;RestorePurchase&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now, this is where things get FUNKY and weird because iOS and Android differ so much.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;iOS&lt;/strong&gt; : returns every single transaction including the original purchase and all renewals with proper transaction date time stamps!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android&lt;/strong&gt; : Only returns current valid subscriptions and the time stamp is always the original purchase date of the subscription, not the renewals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I personally prefer the iOS mechanism for this as it makes the code much cleaner. All you must  do is order the purchases descending by transaction date and compare dates to see if a subscription is valid. On Android, if it returns a subscription then it is valid and you must figure out the expiration date manually by adding time over and over to the original transaction date, which seems problematic. However, after much testing, here is what I came up with to check to see if the subscription has been renewed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;RestorePurchases&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsBusy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IsBusy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&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;connected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConnectAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;connected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&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;foundStuff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&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;subs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPurchasesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ItemType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;productIdSub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;false&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;sorted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;productIdSub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderByDescending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionDateUtc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&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;recentSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recentSub&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// On Android as long as you have one here then it is valid subscription&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DevicePlatform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;foundStuff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasTippedSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                    &lt;span class="c1"&gt;//loop through transactions and keep adding a month until valid&lt;/span&gt;
                    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recentSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionDateUtc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMonths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubExpirationDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="nf"&gt;SetPro&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recentSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionDateUtc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSubTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;foundStuff&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasTippedSub&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckSubStatus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubExpirationDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recentSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionDateUtc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSubTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                        &lt;span class="nf"&gt;SetPro&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DevicePlatform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Android&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;recentSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAcknowledged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;try&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcknowledgePurchaseAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recentSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PurchaseToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to acknowledge purchase: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;foundStuff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hmmmm!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Looks like we couldn't find any subscription renewals, check your purchases and restore them in settings. Don't worry, all of your ride data will be saved."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Status Refreshed!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Thanks for being awesome and subscribing for another month of My Cadence Pro!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Issue connecting: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Uh Oh!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Looks like something has gone wrong, please check connection and restore in the settings. Code: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsBusy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;SetPro&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;CrossInAppBilling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DisconnectAsync&lt;/span&gt;&lt;span class="p"&gt;();&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;p&gt;It is not pretty, but totally working well. Note that for iOS I take the most recent subscription, add time, and compare it with the current UTC time: &lt;code&gt;recentSub.TransactionDateUtc.AddSubTime() &amp;gt; DateTime.UtcNow&lt;/code&gt; and if it is still valid then I update the expiration date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying &amp;amp; restoring a subscription
&lt;/h2&gt;

&lt;p&gt;One important feature that your app must implement is a "Restore Purchases" feature for in-app purchases and subscriptions. This is important if your user gets a new device, has multiple devices, or uninstalls and re-installs the app. I add a button directly on the settings/upgrade screen to do this. The application logic is actually the same as the renewal check above! Code re-use to the max!!! You may have other in-app purchases that you may want to put in there as well, so be sure to restore all your purchases!&lt;/p&gt;

&lt;h2&gt;
  
  
  Receipt validation
&lt;/h2&gt;

&lt;p&gt;At this point we have finished all the in-app code for subscriptions, renewals, and restoration. See, it wasn't that bad :).... well except that we haven't done any receipt validation, which means the user could have cancelled, asked for a refund, paused a subscription, or who knows what else. Oh, and receipt validation also ensures that users haven't hacked your app in some way to intercept the calls to get free stuff. Look how easy this looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZV0WrGin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZV0WrGin--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image.png" alt="Implementing In-App Subscriptions in iOS &amp;amp; Android with no backend servers" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Receipt validation is super important, and I recommend you checkout my &lt;a href="https://jamesmontemagno.github.io/InAppBillingPlugin/SecuringPurchases.html"&gt;documentation&lt;/a&gt;with tons of links to other important resources including how to use Azure Functions as a receipt validation service. For this blog, and in my apps currently I am not doing receipt validation. I haven't personally had any issues, but my apps are only downloaded a few thousand times, not millions of times. So, I am going to leave this up to you based on your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing subscriptions
&lt;/h2&gt;

&lt;p&gt;Now is the fun part of testing!!!!!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14ul10fs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14ul10fs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-2.png" alt="Implementing In-App Subscriptions in iOS &amp;amp; Android with no backend servers" width="433" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the worst part because when you test everything is different in a sandbox, and each platform is different. I ended up using TestFlight and Google Play Internal rings for testing with my normal account. When you subscribe on iOS and Android you aren't charged anything during testing, but they do renew differently for testing purposes. Android will just continue to renew every 5 minutes (for a 1 month sub, longer for others) and then you have to manually cancel the subscription. I like this approach a lot as it doesn't clutter up all my transactions and lets me do more realistic world testing. iOS is a bit of an interesting one as it also will renew the subscription every 5 minutes but will do it up to 12 times and then stop renewing. This is a fine approach, but I just wish they worked the same.&lt;/p&gt;

&lt;p&gt;I could write for days on testing and all the complexity, but there is an amazing &lt;a href="https://www.revenuecat.com/blog/the-ultimate-guide-to-subscription-testing-on-ios"&gt;blog for iOS testing from RevenueCat&lt;/a&gt; that saved my life and outlines everything you need to know. Google actually has pretty good documenation for this and really helped me get through the process. Take your time on &lt;a href="https://developer.android.com/google/play/billing/test"&gt;testing&lt;/a&gt; and make sure to test all of the different scenarios. One pro tip that I can offer is to change the amount of time for a valid subscription to 5 minutes (instead of my 1 month &amp;amp; 5 days) so you can test out the duration that Apple/Google renew on. Once you have validated that you can change it back and ship to the store.&lt;/p&gt;

&lt;h2&gt;
  
  
  In-App Subscriptions SaaS... RevenueCat
&lt;/h2&gt;

&lt;p&gt;Implementing in-app subscriptions can be extremely complicated and can get even more complicated when you throw in user accounts, third party integrations, and subscriptions on the web. After reading the testing blog on &lt;a href="https://www.revenuecat.com/"&gt;RevenueCat&lt;/a&gt;, I realized that it was an entire SaaS solution for in-app subscriptions and is genius.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_-b7sOiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-b7sOiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2022/02/image-3.png" alt="Implementing In-App Subscriptions in iOS &amp;amp; Android with no backend servers" width="587" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are really looking for a full solution this may be a good option for you to investigate. I have still decided to roll my own and use the raw APIs of the platform, but I have to say RevenueCat is pretty awesome and just shows how complex these APIs and testing matrixes are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Considerations
&lt;/h2&gt;

&lt;p&gt;In-app subscriptions are pretty neat as they offer a lot of flexibility over a single IAP or up-front app purchase. For example you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offer a free trial for a month&lt;/li&gt;
&lt;li&gt;Offer discounted rate for the first X months&lt;/li&gt;
&lt;li&gt;Offer discounts for longer subscriptions&lt;/li&gt;
&lt;li&gt;Promote them in the app store as another entry (iOS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is true that we are becoming a subscription based society and some people hate subscriptions. However, if you have great features and want to help your long-term development it is a great option to generate revenue. One option that I have in my apps is the option to do a "life time" subscription purchase. This is actually not a subscription, but a non-consumable in-app purchase. This adds a bit of complexity to the mix, but I think it is worth it at the end of the day. I hope that you found this blog a bit interesting and helpful on your IAP journey!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>xamarin</category>
      <category>ios</category>
      <category>android</category>
    </item>
    <item>
      <title>Celebrate the .NET 20th Anniversary with the Community!</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Wed, 02 Feb 2022 19:18:32 +0000</pubDate>
      <link>https://dev.to/dotnet/celebrate-the-net-20th-anniversary-with-the-community-47e3</link>
      <guid>https://dev.to/dotnet/celebrate-the-net-20th-anniversary-with-the-community-47e3</guid>
      <description>&lt;p&gt;Did you know that this month marks .NET's 20th anniversary! That's right, .NET launched 20 years ago on February 13th, 2002, alongside Visual Studio .NET. We are celebrating all month long and you can get join in on the fun. &lt;/p&gt;

&lt;h2&gt;
  
  
  20th Anniversary Celebration.
&lt;/h2&gt;

&lt;p&gt;The .NET team is throwing a huge celebration on &lt;strong&gt;February 14th at 9AM Pacific&lt;/strong&gt;. This 30-minute event will feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interviews with luminaries &amp;amp; Microsoft alumni&lt;/li&gt;
&lt;li&gt;Stories from customers and developers building amazing things&lt;/li&gt;
&lt;li&gt;Memories of building .NET with Scott Hunter, Scott Hanselman, and special guests&lt;/li&gt;
&lt;li&gt;…and so much ❤ from OSS contributors, MVPs, and .NET team members&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Head over to &lt;a href="//dotnet.microsoft.com"&gt;https://dotnet.microsoft.com/&lt;/a&gt; for more information about the event, but it is never too early to start celebrating! And while you are there, checkout new homepage redesign and the awesome .NET timeline!&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%2Fvc9ts7jbj0f4ne0ber7q.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%2Fvc9ts7jbj0f4ne0ber7q.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Digital Swag (wallpapers, cake designs, and more!)
&lt;/h2&gt;

&lt;p&gt;The .NET design team has put together an awesome array of digital goodies for you to celebrate including wallpapers, Teams backgrounds, cake designs, e-mail signature images, and a whole lot more. They are high-res and customizable with SVGs, here is my current wallpaper on my ultra-wide:&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%2Fx0a3x747zt3kzzyfylmg.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%2Fx0a3x747zt3kzzyfylmg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://github.com/dotnet-presentations/dotNET20th" rel="noopener noreferrer"&gt;https://github.com/dotnet-presentations/dotNET20th&lt;/a&gt; to grab all of the goodies and start celebrating! &lt;/p&gt;

&lt;h2&gt;
  
  
  Mod the dotnet-bot
&lt;/h2&gt;

&lt;p&gt;The dotnet-bot is the mascot for the .NET community. Create your coding companion by &lt;a href="https://mod-dotnet-bot.net/" rel="noopener noreferrer"&gt;modding the dotnet-bot&lt;/a&gt; and then share your creation with the world.&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%2Fwlhtw9k9pxcz42lx6pep.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%2Fwlhtw9k9pxcz42lx6pep.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Celebrate on social
&lt;/h2&gt;

&lt;p&gt;Celebrate with the community throughout the month of February on social media. Have a fond memory? Still have that PDC conference badge? Did you build something amazing? Share your stories, memorabilia, favorite features, etc. in picture or video form on Twitter using the hashtag #dotNETLovesMe. Microsoft, the .NET Foundation, and ecosystem partners are joining the celebration with digital swag, trivia games and more. &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%2F9eey9lbf5dp3hgkjuup3.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%2F9eey9lbf5dp3hgkjuup3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't forget to add the 20th anniversary event to your calendar over at &lt;a href="//dotnet.microsoft.com"&gt;https://dotnet.microsoft.com/&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>fsharp</category>
    </item>
    <item>
      <title>Learn F# this week with Free Events &amp; Live Streams</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Tue, 27 Jul 2021 22:18:35 +0000</pubDate>
      <link>https://dev.to/dotnet/learn-f-this-week-with-free-events-live-streams-3aih</link>
      <guid>https://dev.to/dotnet/learn-f-this-week-with-free-events-live-streams-3aih</guid>
      <description>&lt;p&gt;There are several upcoming events and live streams focus on all things &lt;a href="https://dotnet.microsoft.com/languages/fsharp"&gt;F#&lt;/a&gt;, an open-source language that makes it easy to write succinct, robust, and performant code. Check them out!&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://focus.dotnetconf.net/"&gt;.NET Conf - Focus on F#&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/i3qEhwcG7ps"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;.NET Conf: Focus on F# is a free, one-day livestream event that features speakers from the community and Microsoft teams working on and using the F# language. Learn how F# lets you write succinct, performant, and robust code backed by a powerful type system and the .NET runtime you can trust to build mission-critical software.&lt;/p&gt;

&lt;p&gt;Hear from language designers and experts using F# in a variety of ways from building minimal web APIs to performing data manipulation, interactive programming, machine learning, and data science.&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Thursday July 29th 08:00 (PT) | 15:00 (UTC)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Tune in at &lt;a href="https://focus.dotnetconf.net/"&gt;https://focus.dotnetconf.net/&lt;/a&gt; on July 29, ask questions live, and learn about what F# can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agenda
&lt;/h2&gt;

&lt;p&gt;Browse the full agenda for the 8 hours event at  &lt;a href="https://focus.dotnetconf.net/agenda"&gt;https://focus.dotnetconf.net/agenda&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET - F#&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/u92dj5h4nrA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walk through the fundamentals of F# (pronounced “F-sharp”). F# is a functional programming language that runs on .NET and supports object-oriented programming. The type system and unique features of this language make a great fit for data science and ML. Come learn something new and leave with something that we all built together, live with experts. Streaming LIVE on Learn TV!&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Friday, July 30th at 8:30 AM - 10:30 AM (PT) | 15:30 - 17:30 (UTC)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt;. Sign-in, ask questions, and learn how to start building accessible apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agenda
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introductions: Meet the team!&lt;/li&gt;
&lt;li&gt;Fundamentals: &lt;a href="https://aka.ms/Fsharp_Resources"&gt;Introduction to F#&lt;/a&gt; (20 mins)&lt;/li&gt;
&lt;li&gt;Workshop I: &lt;a href="https://dotnet.microsoft.com/learn/languages/fsharp-hello-world-tutorial/intro/?WT.mc_id=dotnet-29448-jasingl"&gt;F# - Hello World&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Q&amp;amp;A (10 mins): Get your questions answered live!&lt;/li&gt;
&lt;li&gt;Workshop II (35 mins): &lt;a href="https://docs.microsoft.com/dotnet/fsharp/introduction-to-functional-programming/?WT.mc_id=dotnet-29448-jasingl"&gt;Introduction to Funcational Programming&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Q&amp;amp;A (10 mins): Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aka.ms/Fsharp_Resources"&gt;F#resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dot.net/videos"&gt;.NET 101 Videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fsharp</category>
      <category>dotnet</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Let's Learn .NET - Blazor - Free Live Stream Event</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Mon, 21 Jun 2021 19:02:52 +0000</pubDate>
      <link>https://dev.to/dotnet/let-s-learn-net-blazor-free-live-stream-event-5afd</link>
      <guid>https://dev.to/dotnet/let-s-learn-net-blazor-free-live-stream-event-5afd</guid>
      <description>&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walks through the fundamentals of using C# and .NET. This month, we are looking at Blazor and how to use it to build web apps completely in C#.&lt;/p&gt;

&lt;p&gt;Blazor lets you build interactive web UIs using C# instead of JavaScript. Blazor apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries. Together, we will learn all about Blazor and why you would use it to build web apps, and then we will build our first client web app with Blazor and .NET.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4Xzx7Cm9ykg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Friday, June 25th at 8:30 AM - 10:30 AM Pacific&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt;. Sign-in, ask questions, and learn how to start building accessible apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introductions (5 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meet the team!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals (20 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazor101 

&lt;ul&gt;
&lt;li&gt;What is ASP.NET Core? How does Blazor fit in?
&lt;/li&gt;
&lt;li&gt;Why would I build apps with Blazor? &lt;/li&gt;
&lt;li&gt;How does Blazor Work? &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pre-requisites &amp;amp; installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop I (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/build-blazor-webassembly-visual-studio-code?WT.mc_id=dotnet-22477-jasingl"&gt;Build a web app with Blazor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop II (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/modules/publish-app-service-static-web-app-api-dotnet?WT.mc_id=dotnet-22477-jasingl"&gt;Publish a Blazor web app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aka.ms/Blazor_Resources"&gt;Blazor resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dot.net/videos"&gt;.NET 101 Videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>blazor</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Let's Learn .NET - Accessibility - Free Live Stream Event</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Tue, 18 May 2021 21:42:53 +0000</pubDate>
      <link>https://dev.to/dotnet/let-s-learn-net-accessibility-free-live-stream-event-241o</link>
      <guid>https://dev.to/dotnet/let-s-learn-net-accessibility-free-live-stream-event-241o</guid>
      <description>&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walks through the fundamentals of using C# and .NET. This month, we are taking a look at how to make our mobile, desktop, and web apps more accessible. &lt;/p&gt;

&lt;p&gt;Technology can empower people to achieve more, help strengthen education opportunities, and make the workplace more inviting and inclusive for people with disabilities. With more than 1 billion people with disabilities in the world, accessibility and inclusion are essential to empowering every person and organization to achieve more. Let’s learn about building web and mobile applications with accessibility in mind. Together, we will understand what it means to be “accessible”, how to get started directly from your browser, and then what tools you can use to learn more!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ttxAYDMKtSs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Friday, May 21st at 8:30 AM - 10:30 AM Pacific&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt;. Sign-in, ask questions, and learn how to start building accessible apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introductions (5 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meet the team!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals (20 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessibility 101 

&lt;ul&gt;
&lt;li&gt;What does it mean to be “accessible”? &lt;/li&gt;
&lt;li&gt;How can you build with accessibility in mind? &lt;/li&gt;
&lt;li&gt;What tools can you use to build inclusively?
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pre-requisites &amp;amp; installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop I (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/modules/xamarin-forms-accessibility/"&gt;Create accessible apps with Xamarin.Forms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop II (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/modules/aspnet-core-accessibility/"&gt;Create accessible web apps with ASP.NET Core&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aka.ms/Accessibility_Resources"&gt;Accessibility Resources for .NET&lt;/a&gt;!
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dot.net/videos"&gt;.NET 101 Videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>a11y</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Let's Learn .NET - C# - Free Live Stream Event</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Thu, 22 Apr 2021 22:59:21 +0000</pubDate>
      <link>https://dev.to/dotnet/let-s-learn-net-c-free-live-stream-event-1ak0</link>
      <guid>https://dev.to/dotnet/let-s-learn-net-c-free-live-stream-event-1ak0</guid>
      <description>&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walks through the fundamentals of using C# and .NET. This month, let’s start at the beginning with learning a modern, productive, and evolving programming language C#. C# (pronounced See-Sharp) is an open-source type-safe programming language that is part of .NET That enables you to build any type of application including mobile, web, cloud, desktop, IoT, and more. Together, we will learn what C# is, how to get started learning directly from the browser, and then what tools you can install to learn more!&lt;/p&gt;

&lt;p&gt;This fun, beginner's series will teach you all about the fundamentals of everyday technologies and how you can master them using C# and .NET.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Fn28yINqNfo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Friday, April 30th at 8:30 AM - 10:30 AM Pacific&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt;. Sign-in, ask questions, and learn how to start programming with C#.&lt;/p&gt;

&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introductions (5 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meet the team!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals (20 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C# 101  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is C#?
&lt;/li&gt;
&lt;li&gt;What can you build with C#?&lt;/li&gt;
&lt;li&gt;How can you contribute to C#?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pre-requisites &amp;amp; installation  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop I (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/paths/csharp-first-steps?WT.mc_id=dotnet-22477-jasingl"&gt;Take your first steps with C#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop II (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/paths/csharp-first-steps?WT.mc_id=dotnet-22477-jasingl"&gt;Continuing first steps with C#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Special Guest (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Special guest appearance to share some awesome updates about education!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aka.ms/letslearnchallenge"&gt;Join the Cloud Skills Challenge on Microsoft Learn&lt;/a&gt;!
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dot.net/videos"&gt;.NET 101 Videos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Code Generation from XAML in Visual Studio is Mind-blowing Awesome</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Sat, 27 Mar 2021 18:57:22 +0000</pubDate>
      <link>https://dev.to/dotnet/code-generation-from-xaml-in-visual-studio-is-mind-blowing-awesome-41m7</link>
      <guid>https://dev.to/dotnet/code-generation-from-xaml-in-visual-studio-is-mind-blowing-awesome-41m7</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C_3CKHtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/Capture.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C_3CKHtH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/Capture.PNG" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The more and IDE or code editor can do for you the better I say. Visual Studio has been crushing it with new refactorings, IntelliSense, and &lt;a href="https://visualstudio.microsoft.com/services/intellicode/"&gt;IntelliCode&lt;/a&gt;, one of my favorite features ever. One thing that I have always been hoping for as a XAML developer is deeper connectivity between the XAML and the View-Model. We have seen increased IntelliSense in this area, but with the release of &lt;a href="https://devblogs.microsoft.com/visualstudio/vs2019-v16-9-and-v16-10-preview-1/"&gt;Visual Studio 2019 v16.9&lt;/a&gt; comes code generation from XAML! That is right, you can now have Visual Studio automatically create your properties, commands, and more!&lt;/p&gt;

&lt;p&gt;I will walk through this awesome feature for Xamarin.Forms, WPF, and UWP, but if you just want to see it in action, I made an entire video:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/YX04sxwLMBE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling Code Generation
&lt;/h2&gt;

&lt;p&gt;The first thing to do is to create your &lt;code&gt;ViewModel&lt;/code&gt; and implement INotifyPropertyChanged (or inherit from something that does). Then just create a control with a &lt;code&gt;Binding&lt;/code&gt; associated with it. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;StackLayout&amp;gt;
    &amp;lt;Label Text="{Binding Text}"/&amp;gt;
&amp;lt;/StackLayout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you do this, Visual Studio will put little dots under the &lt;code&gt;Text&lt;/code&gt; binding and a lightbulb will show up (if you don't see this simply re-compile). The lightbulb will look to assign your &lt;code&gt;x:DataType&lt;/code&gt; in Xamarin.Forms or &lt;code&gt;d:DataContext&lt;/code&gt; in WPF/UWP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KqJNMrLv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KqJNMrLv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="670" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I selected this option, it auto added the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xmlns:app1="clr-namespace:App1"
x:DataType="app1:MyViewModel"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is &lt;code&gt;x:DataType&lt;/code&gt; you may be asking? Well, it is a &lt;a href="https://dev.toxmlns:app1=%22clr-namespace:App1%22%20%20%20%20%20%20%20%20%20%20%20%20%20%20x:DataType=%22app1:MyViewModel%22"&gt;compiled binding&lt;/a&gt;, which makes your bindings and apps faster! This is an awesome feature of Xamarin.Forms that you should totally use!&lt;/p&gt;

&lt;p&gt;With this code in place, you will now see the dots remain and a new lightbulb show up to create a property called &lt;code&gt;Text&lt;/code&gt; for you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARXy7k1R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image-1-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARXy7k1R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image-1-1.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, it is recommending adding the property and creating a &lt;code&gt;SetProperty&lt;/code&gt; method to invoke &lt;code&gt;PropertyChanged&lt;/code&gt;, which is AWESOME!!!! Now, at this point you probably want to refactor the code a little bit and create  &lt;code&gt;BaseViewModel&lt;/code&gt; that you put this method in and then in future ViewModels it will not attempt to create the code and just add the property. If you are using &lt;a href="https://github.com/jamesmontemagno/mvvm-helpers"&gt;Mvvm Helpers,&lt;/a&gt; you can use this code as your base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ViewModelBase : BaseViewModel
{
    public bool SetProperty&amp;lt;T&amp;gt;(ref T field, T newValue, [CallerMemberName] string propertyName = null) =&amp;gt;
        SetProperty&amp;lt;T&amp;gt;(ref field, newValue, propertyName, null, null);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you add another control with another binding, you will see nice tight code will be generated for you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--57wvYmXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/a3029627-a5f7-4b25-9f9a-46b9640d7b65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--57wvYmXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/a3029627-a5f7-4b25-9f9a-46b9640d7b65.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is your mind blown yet?!?!? Mine is! However, it gets even better!&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Commands!
&lt;/h2&gt;

&lt;p&gt;Now, let's say we are going to add a &lt;code&gt;Command&lt;/code&gt; to a &lt;code&gt;Button&lt;/code&gt; we would naturally want that code to be generated as well, correct? Well, you are in luck because it will!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r-vmBOud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/549b7ca7-2b48-4847-905c-44b8bc8bb91c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r-vmBOud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/549b7ca7-2b48-4847-905c-44b8bc8bb91c.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code is really neat because it not only created the command and the method, but it also brought in the correct namespace to use the Xamarin.Forms &lt;code&gt;Command&lt;/code&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Command Generation on UWP/WPF
&lt;/h3&gt;

&lt;p&gt;If you are over on UWP or WPF you will not see this code generation because the core framework does not have an implementation of &lt;code&gt;ICommand&lt;/code&gt;. However, if you are using a framework or library such as Mvvm Helpers then it will be smart enough to figure it out and recommend code for you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MbrJ9ilk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/d91d33e6-b81f-458d-b8e3-e03c0345f134.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MbrJ9ilk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/d91d33e6-b81f-458d-b8e3-e03c0345f134.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MIND BLOWN!!!! ARE YOU NOT IMPRESSED!?!?!? Amazing!&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleaner Code with C# 8 &amp;amp; 9!
&lt;/h3&gt;

&lt;p&gt;One of the things you may have noticed is that the code for Xamarin.Forms and WPF/UWP are different in the screenshots. That is because my WPF sample app is using .NET 5, which uses C# 9 by default. The Xamrin.Forms app is using .NET Standard 2.0, which defaults to C# 7. However, you can easily adjust what version of C# is used in your project by adding the &lt;code&gt;LangVersion&lt;/code&gt; into your csproj.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;LangVersion&amp;gt;8.0&amp;lt;/LangVersion&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at my &lt;a href="https://montemagno.com/enabling-c-9-in-xamarin-net-standard-projects/"&gt;previous blog about upgraded a project to C# 9&lt;/a&gt; in a minute.&lt;/p&gt;

&lt;p&gt;Once you upgrade to 8.0 or higher the old code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private ICommand clickCommand;

public ICommand ClickCommand
{
    get
    {
        if (clickCommand == null)
        {
            clickCommand = new Command(Click);
        }

        return clickCommand;
    }
}

private void Click()
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will be upgraded to this lovely clean tight code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private ICommand clickCommand;
public ICommand ClickCommand =&amp;gt; clickCommand ??= new Command(Click);

private void Click()
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code Generation for Models
&lt;/h2&gt;

&lt;p&gt;So far we have had Visual Studio generate code in our ViewModel classes on our page, but what about our models that are bound to an &lt;code&gt;ItemsSource&lt;/code&gt; in a &lt;code&gt;ListView&lt;/code&gt; or &lt;code&gt;CollectionView&lt;/code&gt; Well no worries, all you need to do is set your &lt;code&gt;x:DataType&lt;/code&gt; on your &lt;code&gt;DataTemplate&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ListView ItemsSource="{Binding Items}"&amp;gt;
    &amp;lt;ListView.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate x:DataType="app1:Item"&amp;gt;
            &amp;lt;ViewCell&amp;gt;
                &amp;lt;Label Text="{Binding Text}"/&amp;gt;
            &amp;lt;/ViewCell&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/ListView.ItemTemplate&amp;gt;
&amp;lt;/ListView&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you will see lightbulbs on any control inside of the &lt;code&gt;DataTemplate&lt;/code&gt;!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4o2zF8RN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4o2zF8RN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://montemagno.com/content/images/2021/03/image-5.png" alt="Code Generation from XAML in Visual Studio is Mind-blowing Awesome" width="880" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, this is pretty mind blowing and amazing! I was able to create all of my ViewModels and Models all without leaving the XAML!&lt;/p&gt;

&lt;h2&gt;
  
  
  Just the start!
&lt;/h2&gt;

&lt;p&gt;This is all from me just playing around with Visual Studio 2019 v16.9 for a few minutes exploring this awesome new feature. There is for sure much more to come as &lt;a href="https://twitter.com/MarcoOGoertz/status/1375544055598215171"&gt;Marco&lt;/a&gt; from the XAML Tooling team tweeted about the new feature and discussed with commentors about extending the templates for code that is being generated. Also, as of right now this is just a feature on Visual Studio on Windows, but since Visual Studio for Mac uses pretty much the same engine, we can imagine it will make its way to VSM soon.&lt;/p&gt;

&lt;p&gt;This is just one of the many features that was included in Visual Studio 2019 v16.9 so check the &lt;a href="https://docs.microsoft.com/visualstudio/releases/2019/release-notes"&gt;release notes&lt;/a&gt; and upgrade today!&lt;/p&gt;

</description>
      <category>xaml</category>
      <category>visualstudio</category>
      <category>xamarinforms</category>
      <category>uwp</category>
    </item>
    <item>
      <title>Let's Learn .NET - Microservices - Free Live Stream Event</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Mon, 22 Mar 2021 17:30:44 +0000</pubDate>
      <link>https://dev.to/dotnet/let-s-learn-net-microservices-free-live-stream-event-1lg0</link>
      <guid>https://dev.to/dotnet/let-s-learn-net-microservices-free-live-stream-event-1lg0</guid>
      <description>&lt;p&gt;&lt;a href="https://aka.ms/letslearndotnet"&gt;Let's Learn .NET&lt;/a&gt; is a monthly beginner series that walks through the fundamentals of using C# and .NET. This month, jumpstart your experience building Microservices with .NET! Learn about what microservices are, why you need them, and how to build them with C# and .NET. You will leave with an understanding of how a container, images, hub, and orchestrator all relate to each other. &lt;/p&gt;

&lt;p&gt;This fun, beginner's series will teach you all about the fundamentals of everyday technologies and how you can master them using C# and .NET.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/sstOXCQ-EG0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;Friday, March 26th at 8:30 AM - 10:30 AM Pacific&lt;/p&gt;

&lt;h2&gt;
  
  
  Where
&lt;/h2&gt;

&lt;p&gt;Streaming live for FREE on &lt;a href="https://docs.microsoft.com/learn/tv/?WT.mc_id=dotnet-17847-jasingl"&gt;Microsoft Learn TV&lt;/a&gt;. Sign-in, ask questions, and learn how to build Microservices with .NET, Docker, and Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Come learn something new and leave with something that we all built, together, live with experts. Here is the agenda for the event:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introductions (5 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meet the team!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals (20 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Microservices 101 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are microservices?
&lt;/li&gt;
&lt;li&gt;Why are they important? &lt;/li&gt;
&lt;li&gt;What tooling is needed for development? &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pre-requisites &amp;amp; installation  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop I (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/learn/aspnet/microservice-tutorial/intro?WT.mc_id=dotnet-17847-jasingl"&gt;Learn how to build &amp;amp; deploy your first Microservice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workshop II (35 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/learn/modules/microservices-aspnet-core?WT.mc_id=dotnet-17847-jasingl?WT.mc_id=dotnet-17847-jasingl"&gt;MS Learn - Create &amp;amp; deploy a cloud-native microservice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q&amp;amp;A (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get your questions answered live!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Open Discussion (10 mins):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's discuss the learnings and what else is on your mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RSVP Today
&lt;/h2&gt;

&lt;p&gt;Head to &lt;a href="https://aka.ms/letslearndotnet"&gt;aka.ms/letslearndotnet&lt;/a&gt; to RSVP today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for more?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/learn/challenges?id=c9730dd9-062b-4433-b73e-265a2ed233c4"&gt;Join the Cloud Skills Challenge on Microsoft Learn&lt;/a&gt;!  &lt;/p&gt;

&lt;p&gt;Microservice architecture is a style that structures an application as a collection of services which are highly maintainable &amp;amp; testable, loosely coupled, independently deployable, organized around business capabilities, and owned by a small team. Follow this challenge to skill up on using .NET and microservices.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>beginners</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
