>> 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.