Create native desktop & mobile apps using web skills in Blazor Hybrid | .NET Conf 2022

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
>> Hi, I'm Eilon Lipton and as our amazing host, just let you know we are here to talk about Blazor hybrid and we are doing a hybrid talk. I am here in the studio and off to you, James. >> Hey I'm James, I can't see you. I'm following the steady cam behind the scenes so maybe Cam can update that. Who knows. But it's cool because I'm watching behind the scene that is really amazing what's happening. But yeah, this is literally a hybrid talk about Hybrid development, and Eilon you came up with the most generic title ever, which is create native desktop and mobile apps using web skills and Blazor or hybrid, that we're talking about today, I feel like when we rehearsed this, that is not what we're going to talk about. >> I think we changed it up a little bit. The real name we might want to give this talk is maybe we'll switch it to slay the competition. No, kill the competition by slaying them with Blazor Hybrid apps. Settled to extreme James, and we can get in trouble for that. Should we quickly change the title to something else? >> How about tips and tricks for building hybrid apps with Blazor and.NET MAUI. I feel like that's really click Beidi on YouTube and things like that. Now. >> I think that could work, James. >> Maybe I'll narrow it down a little bit even more because we only have 25 minutes Eilon. Well have I'll just top tips, four. >> Four top tips, do you think we can do four? Let's give it a shot. >> I think we can do four. I'm really excited because if you know my background, I come from the Xamarin and [inaudible] world and Eilon literally works on the Blazor Hybrid team, nearly built half the thing and all the amazing things, which is cool. We've got web development. You got client development, as Maddy would say, PB and J, or if you're like me, peanut butter and more peanut butter. Because Madonna developers, when we think about it, Donald's developers your jelly and jellies live your life, I say because I think the dream and why I love being a dominant developer is because I can build for any single platform and you can build for any single platform, whether it's web desktop, mobile games, IoT, AI and mix and match that technology around. You could build an amazing IDs and code editors build on different operating systems for different operating systems and really get involved in the community and take advantage of the amazing ecosystem. We're going to focus on this, peanut butter and jelly right here, which is the web and desktop and mobile, we call it client development, often your clients, but that's really for clients like your phone or that top right there or my desktop here, we're talking about. Normally, these worlds are split apart. I just said, I'm a client developer and Eilon's a web developer, but why can't we work together and why couldn't Eilon build desktop and mobile apps? Why couldn't I build web applications using similar technologies? ASP.NET Core is a series of different services and web UI technologies and the one that we like to talk about is all of them but the one that I love talking about is Blazor. Because for me, the power of Blazor is really tapping in to building rich web applications with all C-Sharps. I don't have to learn JavaScript. I think coming from the client world alone, it's actually very natural for me to build Blazor applications because as a client developer with.NET, I'm in C-Sharp everyday. >> Absolutely. One of the things with Blazor also, as you mentioned, you get to stick to C-Sharp and Visual Studio, which we know a lot of folks are very happy with and there's a huge ecosystem of components out there. There's a lot of knowledge and docs and tutorials, videos, sessions from past.NET Conf. There are some sessions earlier today that folks and watch it On-Demand a little bit later and everything there that you see that says Blazor on it applies equally in this session as well, as long as it's talking about building Blazor components, rendering some HTML, handling events in the background. All of that makes just as much sense in everything that James and I are going to talk about here now. >> One of the powers of this, where no matter what you're building, whether it is with Blazor or something else, is.NET Razor components. Those components is really swot this amazing. Rich ecosystem of Razor components can be shared anywhere. If you're already building MVC or Razor Page applications, those can come over via the Razor components into Blazor applications and what we'll show you is to more places as well. Like I said, Blazor is a full-stack web app platform for.NET so you can build and deploy on the server with Blazor server or directly in the browser at Blazor WebAssembly. We're going to talk about the third option for Blazor that doesn't require the server and it doesn't require WebAssembly at all, which is Blazor Hybrid. Blazor Hybrid, I wouldn't actually call it really a third motive Blazor I think when you and I talk about Eilon, It's really like bringing the ability to leverage Razor components and Blazor technology in other development frameworks such as WPF, WinForms, and.NET MAUI. Anything that we talk about today, what we'll focus on.NET MAUI also applies to WPF and WinForms. That's how we like to look at it there. Now if you haven't been watching the last 90 minutes or the keynote, you may not be like what is.ml lets a multi-platform app UI is the evolution of Xamarin Forms and then gives you, as a developer, a unified platform to build native client applications for Windows, Mac, iOS, and Android from Visual Studio with.NET. What this gives you at the end of the day, between a Blazor and ASP.NET Core is the full reach. As a developer, you think of the web, you can go absolutely anywhere, whether it's websites running in the browser, on the server or progressive web apps. You can get that depth to deploy an integrate deeply into the native operating systems. No matter what you want to do on iOS, or Android, or Windows, or Mac, you have access to those APIs gets happening as native frameworks that are also important. Then of course, live in between and build these hybrid applications so you can truly deploy anywhere and that's really one of the goals here is I'm going or what you're looking to build, you can reuse and leverage that technology across the web and desktop and more based on what you need to build. I think that that's what is important. We talked about four tips and tricks. Going beyond, File New, How do you feel about that, Eilon? >> Let's do it. Let's jump right on and we got let's see, are we doing a demo right now? These are three topics. Let's write. Four tips, three topics. We're going to talk about sharing state because I think once you get after File New, there's videos that we've done in the past. Dan Rossen in the past. You think about, well, how do you share state, also sharing coding components effectively, and then also doing navigation and considerations you want to take there. Really we're considering this, 2-300 level Blazor or hybrid talk, I would say in general because these are things you're going to run into in the first few weeks. I want you to start us off with Eilon, head over to you our machine, and let's talk about sharing state between our Blazor apps and our.NET MAUI Apps. >> All right. Thank you, James. Here I've got Visual Studio 2022 did a fresh install just a few days ago to get ready for this and everything that we're going to show today applies broadly in almost any Blazor scenario and is going to take advantage of a lot of things that you might already know about Blazor and how to build Blazor applications but in this world of hybrid applications, we're integrating all of Blazor into a.NET MAUI application. First thing I'll show you is this application we're going to work with. We love showing File New. This is just a little bit beyond that, but I'm going to show how to do this more deep integration between the Blazor Hybrid part of the application and the rest of the.NET MAUI app. Now, if you've used Blazor or.NET MAUI before, you've probably seen a template that looks like this, is a simple application with a few tabs. All I did here is, I added this counter at the top here where it says count zero and click button. Guess what? You click the button, the count goes up. However, if I go to the Blazor part of the application, which is this lower portion of the application, you see the counter starts at zero and I can click that. Well, why are there two different counters? They're not sharing state, so we're going to solve that by writing not too much code to wire those up together. Let's jump into that. >> The first thing you want to do when you want to share state is have some object that contains all of your state. Now, I sneakily added this file while no one was looking. I created a class called MySharedState that has just three APIs on it. It's got the current count. That's the actual state we're going to use. It's got a method to increment the count by one and every time I increment the count, I'm also going to invoke an event handler. Any other component in the application that wants to be notified that the count has changed, can hook up this event, and do whatever they need to do to update that part of the application to reflect that new state. Well, I've got this class, but nobody is using this class yet. The first thing we need to do is we go to this file called Maui program.cs that every Maui application has and in here you set up all the common things that your application will be using. The way we share the state is primarily based around dependency injection and we do that by registering, in this case, a singleton class of that mySharedState and what this means is that the first time a part of the application needs to use a mySharedState object. One will be created and from that point on, anytime part of the application needs access to one of these, because it's a singleton. They'll get exactly that same instance. Now we've made that available to the entire application. Let's start using it. Now, we have the native UI part of the application, which in this application is defined in XAMl. That's over here. We've got. This is the label with account. That's the button that you can click and below that is the blazer web view for the lower portion of the application that we saw and here in the code, we need to start using that shared state. The way you generally use dependency injection and these types of applications is through constructor injection. Now, one thing here is that this particular class is not created by the dependency injection container. But this class over here, App.xaml is, so we see here, now there is an error and the constructor for main page because I'm not passing in a required parameter. Let's fix that. Now I'll pass that in. This parameter value is provided by that dependency injection container that was set up in Maui program. We hear registered something for mySharedState type that is automatically available with no extra work on your part. The app developer is available here. We pass that into main page and when we go to the main page, it is available here, but we're not actually using it yet. Now, we saw that on the mySharedState there is account available. Let's first of all store this on some field and the class was moved this up just a little bit, so we have access to it a little bit earlier. Now everywhere in this class where we need to use the shared state, we're just going to use that field. Instead of maintaining our own count, which I have here in this field, I'm going to use that shared state. Here we're updating the label text to say what the current count is. We're going to just use that current count. When the button is clicked, I'm going to call that method that's called IncrementCounter. Now when I run this application or close the file by accident, which is just fine, we should see essentially nothing changed because instead of manually maintaining the count inside the upper portion of the application, I'm just doing it using the shared state class, but I'm not actually sharing any state yet. Let's fix that. The other part of the application is written using these razor components. Here we have a counter.razor file, and this is one of the files that comes from the default template and we're going to do a very similar thing to what we did in the XAML side. The things and here we're going to do it and the razor side of things. Well, because we're sharing state, I don't need to maintain my own count. Let's delete that. I don't need to increment the count here, but how do I get access to that? Well, we use that same dependency injection container and here razor has this built-in feature called @inject where you can inject one of those types that were registered, for example this singleton, mySharedState, and just automatically get it injected here. Instead of using this Currentcount field, which I just deleted doesn't exist we're going to get the value from mySharedState. Whenever the value is incremented or the button is clicked to increment, I'm going to go to mySharedState object. We'll run this application and we should have emphasis on some shared state. Let's check it out. Here I'm going to click the button and it's incrementing, it's updating that shared state object that count to seven. I'll go to this counter here and sure enough, the value here is seven. That is wonderful. But when I click this button, this lower counter is updating, but not the upper one until I cause it to be updated by clicking this button so the count is 7 now, I'll click it and it jumps up to 18. As I click this only the upper one is updating. There's sharing state, but nobody is listening to this event to update the UI so I can update each one individually and pick up from where the shared state left off, but they're not updating each other. That's the last little bit here that we need to wire up. Let's see which one will we do first. Let's go back to the XAML side of things for the native UI. Well, if you remember on this shared state object, every time the count is incremented, I've got this event handler, but nobody's listening to it so that's how we're going to solve this problem. Here in the XAML side of things, I'm going to go to this.mySharedState, and go to the CountChanged event and register an event handler. In this EventHandler well, I could just throw not implemented exception but instead what I will do is I will call my UpdateLabelText method. This way, no matter where in the application somebody somewhere somehow updates the count. I'm going to update my label text and this is just using very standard XAML patterns where I update some binding and then let the XAML engine know that, oh, some property has changed. This one in particular label text so go update the pixels on the screen. The XAML side of things is taken care of and we do a very similar thing inside counter.razor. Here, I place to listen in and wire up some event. In blazor we can do that in an initialized. I'll write essentially the same code as we had before, or at least conceptually the same. I'll hook up here. I'm going to just do it in line. Wire up an event handler to see if I get the syntax right. A lot of interesting characters there and here every time this updates, well, I could call this built-in Blazor API called StateHasChanged, but I'm going to be extra safe. I'm going to call InvokeAsync, which guarantees that this API is called on the right thread. Nearly all UI platforms, including blazor, WPF, when forums you name it you can only do UI updates on the UI thread. What this InvokeAsync built-in called says is make sure that we're only going to update the UI on the UI thread. Now we'll run this. James are your fingers crossed? >> Because I crossed actively all of them. >> Very good. Now we have two parts of the UI. We have this native part of the UI up here on the top using Maui buttons defined in XAML I've updated the countless, get some other number we've already seen seven. Let's get it to 12. When we go here to the Blazor part, it starts at 12:00. Well, we already had that but now every time I click this because we're sharing state and all parts of the application are listening to the event no matter where. I click that button either I'm changing the state up here in the XAML world, or I'm updating it down here, we have this unified shared state all across every part of the application. The same pattern applies whether it's a blazor hybrid application in done it now we or using running on WPF or Wind Forms or if you want to integrate the same model in any other system. This is just standard C-Sharp code. If you've written any C-sharp code in your career or in your hobbies, you've seen code like this. There's nothing special about this and then it was just a few lines of code in the XAML to wire it up with the account changed event and a few lines of code to update it on the blazor side of things. There you have it. SharedState. Let's go back to a James's slides. >> What I love about this alone is that like you said, this is just C-sharp.NET Conf. This is just how in concept you would do it. Now, there are of course, some amazing community packages out there you might find that are doing state management or things like that. We're going to talk about some of the core concepts inside of a Blazor hybrid application with.NET Maui, but the same concepts would actually be true if you had a Blazor app ended on Maui app using Blazor UI, because the next thing you want to do is probably share some of that UI and some of that state across not only your app and the UI components on side of it, but also between multiple apps in general. Some of the same infrastructure. We're going to talk about sharing code and components across a web and you're done MLE Blazor hybrid apps. Because what Eilon just showed if you saw there, is that he showed a single.NET Maui application using Blazor hybrid for the UI. There's nothing special there, just out of the box. Here's what it was. But what do you think about is that you probably also want to build a web application and share some of the business logic like your models and ViewModels and RESTful service calls and controllers and things like that and then you also probably want to share some of the components. How do we do that normally Eilon? How would you normally share code in the world of.NET? >> Absolutely. There's two types of projects that come in very handy for sharing code. The first is one that I would wager every single dot end user ever has used and that's a class library project. It's just a way to package up C-Sharp into a DLL or a new Get-Package and share that amongst multiple projects that you own or publish it up to NuGet and share that with the rest of the world. That's a great way just to package up any C-Sharp code. The next one is a Razor class library. That's how you package up the same type of Razor files that we just saw that I was working on in the previous app. You can package those up and share your UI, you're rendering static assets such as CSS or HTML, images and so forth. Package those up and share them amongst multiple projects or even within your entire company or with the world as a NuGet package. >> What this looks like in practice is that you have your Blazor application and you're.NET Maui application and what's going to be shared across are those class libraries, of same code and then your Razor class libraries as well as many as you want. Now those also could just be new Get-Package is like alongside. That could be there but sometimes you want to access native APIs. For example connectivity or geolocation or sensors and how are you going to do that in a Blazor app, an add-on Maui but we're going to show you because we're going to leverage another class library. Then we'll have our interfaces and then the beautiful part about these frameworks is that you have access to the implementation details for Blazor and also for.NET Maui, and some simple helpers that will even take you further. Eilon, let's go back to your machine and let's talk about how to do that effectively inside a Blazor and.NET Maui with Blazor hybrid. >> Here we're back on my machine with Visual Studio and this is an application that James wrote for monitoring air quality information. Just to show you what the application does is you can enter a location, let's say we've got Seoul, we've got Boston, load up the data, get the air quality information. This tells you how healthy the air outside is to breathe. Let's see if internet it's working. There we go. Oh boy. Seoul, better watch out and Boston, my hometown, the air is wonderful. Go and breathe as much as you can. We've got Maddy over here off to the side. She is very happy about that. That is wonderful. This application, this is a.NET MAUI application built using Blazor hybrid. This same application, we also have a web version of it written using Blazor server and when I get that up and running, you'll see exactly the same UI. We'll go here we'll even show that, well, maybe the air quality has changed in the last few minutes, I don't know, but we'll check Seoul see if the air is doing all right. Not too great there. Watch out any of you.NET developers out in Seoul, Be careful when you go outside. But you see it still has the same UI. Well, how did we do that? Well, we've got the solution here which by the way is up on GitHub, will share a link to that a little bit later, where we've got some shared class library components and some shared Razor components. You see these Razor files, it's the same exact Razor files that you'd use anywhere in your application and this is that air quality information table. This is just running regular old HTML using Blazor syntax, but we want to use the exact same UI amongst multiple different applications. Now, let's see what did we want to show? In here we've got, let's see. I'm going to jump straight ahead to the sharing the connectivity information. One of the bits that we thought was really important in our application is if I go back to the hybrid version, is for the application to be aware of the machines network connectivity status. When I run the.NET MAUI application one more time, hopefully your machine has internet access because that's where it gets the air quality information from, but so here we've got this working and we're going to refresh the data and it's going to load Boston with that beautiful air. I'm going to launch my developer tools here. Actually, you know what, let me do this for the Blazor WebAssembly version first. Launch the Blazor WebAssembly version, set as My Start-up Project, get that running. This is the third version of the application. Here it's working just fine out a location, load the network inspector tool, refresh the data. You'll see here it's making a web request to get air quality information for the backend using Azure functions. But if I switch and say, actually we're offline. You see the application immediately reacted to that and disabled the UI. If I go back online, the application wakes up and we can enter more locations. Let's check out Seattle air and this will continue working as before. Well, depending on whether we're running in.NET MAUI, For example, I have the same application here running in Android, if I go to airplane mode, the same behavior will happen. But the way you detect network connectivity on Android is different from Windows, is different from a Blazor server app, is different from Blazor WebAssembly app. Well, fortunately, C-sharp to the rescue. We've defined this I Air Quality connectivity interface that has two APIs on it, get the current status of connectivity and let me know anytime that it's changed. We're going to use exactly the same techniques we did earlier for sharing state and that's done through dependency injection. If we go again to that same MauiProgram.cs file that we saw on the other project, we register these interfaces and in the MAUI world, we can use it MAUI Essentials, which is a cross-platform library for implementing lots of common functionality amongst different systems, such as detecting network status or doing file pickers and things like that. Even in the Blazor WebAssembly version down here, we've implemented that using JavaScript interrupt. This is implementing that same interface, but in this case, because we're running in a browser, I can talk to the JavaScript system and say, Hey, browser, what's the network status? I think with that, let's go back to you, James. >> Absolutely. I think what's really cool here, when you dive into the demo, it's seeing how we use our own interfaces to use the native functionality on both the browser and in.NET MAUI. In the case of.NET MAUI, that API was already extracted for us. Now, if you want to, you could actually add UseMauiEssentials into any.NET 60.NET 7 project and that will actually bring into interfaces for you if you don't want to create your own. However, one thing to note is that those might not be the interfaces that you want because there are interfaces here that only have async or non-async methods. We recommend here creating your own interfaces, but then of course, using the implementations as you need. Last thing in our last few minutes here is effective navigation. How do you navigate between the different types of applications and what's the best way of doing it? Well, let's take a look here. I'm here and I have that same exact application for Windows, Android, and over here for web. What we've done is we've set it up so if we can navigate, I can click on the specific item. Here we can see that I can click around. Now, we're going to immediately note that we have a few issues like one, on the web, this seems to work pretty great because I can tap on it and hit the back button. Over here, it says air quality Seattle, but I have no back button over here and over here on Android, I have no back button, but I have a physical back button. I'm getting a lot of different functionality and this is because I'm inside of my Blazor application on my Blazor web view and I'm navigating from component to component. That make sense in the web where I can go into this project here and I can look in our pages, in our index, and we can see that I'm using the NavManager here to actually navigate across. If we look at the shared component in our table, what we're doing is we're saying if there is a delegate, go ahead and navigate across, passing the location across. Well, I could use that same exact functionality or I can just navigate across inside of my Blazor hybrid application with.NET MAUI and use that same exact code. Navigate over here to here. This is the NavManager that you know and love and over here we can see that I'm using the router and I'm selling it to scan my assembly and also the shared component assembly. But is that the functionality we want to create the best native experience. What we're actually able to do is leverage either traditional.NET MAUI navigation or our app shell, which does a lot of great parameter routing for us. What I did is I created my own Details page, which is a XAML page, but it has one Blazor web view with that location details component. I'm going to wrap that component in a native page to get native navigation. Now, to do that, all I need to do is come back into my "Main Index" over here and we're going to go ahead and comment back out this code here, which is to use the Shell navigation. Shell.Current.GoToAsync and pass in the location here via URL routing. Just like the web as URL routing, so does.NET MAUI. Here what I'll do is I will automatically pipe this query property across the wire into my details page and then tell my component in the on appearing to use these parameters. I'm cascading the parameters down from my.NET MAUI page into my component, if that makes sense. I think it does. What we hope to see here is that I can still navigate across, but get a back button and use the native navigation. Let's Close that down and then redeploy it. Now, what I love about this is that you are in control of your type of application. If you want to implement your own back stack and back and nav button and you want to use 100 percent.NET MAUI, you could totally do that or 100 percent Blazor so just to say, you could tell it to do that. It's up to you. If you want to use the native navigation like I have here, let's check out Boston again, Refresh that data, we can see it's still amazing. I can click on it and now we can note that I'm not only getting an update in the title, but also getting this nice back button automagically for me and I get those nice animations because that is a native Windows application, just like I would get it there. The other thing too is that on your details page, you now have access to do things like set different presentation modes, like animations, modals, different things. You're incomplete control, which I think is absolutely delightful at the end of the day to create those great experiences. Let's wrap it up because with Blazor hybrid, you can build all amazing things. You can reuse your UI components. You have the native app shell, access to native APIs, there's no WebAssembly, no server needed for the Blazor web view at all and you can use it on top of.NET MAUI or WinForms or WPF. We also showed you how to access native APIs and share state when mixing and matching Web UI as well and sharing components everywhere. You can get access to all of this information, all of our demos on both Eilon and my GitHub right over there. Take a quick snapshot of the UI there. We have great resources to documentation and more information on.NET MAUI and Blazor. With that, along we crushed the 30 minutes and we slayed this presentation.
Info
Channel: dotnet
Views: 11,759
Rating: undefined out of 5
Keywords: .NET, group-client, .NET MAUI, Blazor
Id: ojcvL8KCOwo
Channel Id: undefined
Length: 29min 38sec (1778 seconds)
Published: Wed Nov 09 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.