Daniel Roth & Ed Charbeneau: Blazor ⚡ Beyond the Browser | #twitch #stream

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
it is time to cut the music and go live and with me today is Daniel Roth everyone principal program manager at Microsoft's currently focused on laser and other wonderful asp.net things thanks for joining me Daniel oh it's pleasure to be here thanks for having me ed so we have quite the twitch audience today and it's great to have you with us so Daniel is gonna talk to us today about blazer beyond the web we're going to talk about progressive web apps and all sorts of other great stuff so I'm I'm not gonna delay things any longer Daniel I'm just gonna give you the floor to remind folks that they can and ask questions in chat room I'll try to try to interface there and bubble up the good questions to you or answer directly in chat we also have our telluric staff with us answering questions and giving away prizes so i think we have some prizes to give away today so keep your eye on the chat chat room folks and watch for announcements about those things as well Oh in Chris antes with us too he's going to join us tomorrow on our channel talking about some authentication tomorrow I think later this week though right absolutely so you're welcome to get started Daniel all right let's do this hi everyone welcome my name's Daniel Roth I'm a program manager on the asp.net team I work on our web UI technologies and dotnet and specifically I work on blazer and like head was saying we're gonna try and take blazer beyond the web today in this in this stream now I'm guessing a few of you have wanted to build a web app and then in the past and you know modern web apps have a quite a bit going on if you want to build a sophisticated web app you're gonna need all sorts of stuff you're going to need grids you're gonna need tab views and wizards and dialogues forms and validation to give you that rich interactive UI you probably also need to worry about things like authentication and localization you need your app to be able to target desktop browsers as well as mobile browsers maybe you even want your app to be installable so it can run offline have offline execution and integrate natively with with the OS now historically if you wanted to build such a web application the only real way to do it was to write the entire application in in in JavaScript using a JavaScript framework but you know fortunately thanks to open and modern web standards that's no longer the case blazer is a web UI framework for building rich modern web UI using just dotnet and C sharp with blazer you get the productivity of the c-sharp language you get the great tooling with Visual Studio a stable and consistent ecosystem to build your modern web UI as well as a high-performance dotnet back-end blazer is open source it's cross-platform and it works in any modern web browser using just open web standards no plugins or code translation required now how does that how does that work well blazer actually can function in one of two different ways the first way we call blazer server in a blazer server application your components run on the server using dotnet core and all of the UI interactions are handled over a real-time WebSocket connection with the browser all the UI events get sent to the server your components handle them they render and then all the UI updates get sent back to the browser laser server is great because the download size of the app is very very small it's very thin all of the hard work he was being handled on the server so it works well on on low powered devices and because your code is already on the server and stays on the server I can really simplify your app architecture believes the server has has shipped for a while now it actually shipped last year first with.net core 3 oh and the again with the dotnet core 3.1 long-term support release LTS release now the second way that a blazer app can can run yeah we call blazer webassembly a blazer webassembly app runs directly in the browser using a web assembly based dotnet runtime that you can deploy with your app you then build your web UI components using c-sharp and net and you download them into the browser and just run them using that run time again the components run the handle UI events they render and then the Dom gets efficiently updated directly in the browser blazer web assembly apps are great because they are pure client-side applications they run purely on the user's device they don't require any dotnet on the server at all actually you can deploy them as a pure static site they also because they're running fully on the user's user's device they can even have support offline execution no need to have that persistent network connection like you need with with a blazer server application and the great news is that blazer web assembly is now released just a couple weeks ago at the Microsoft build conference we announced that blazer web assembly is is now available and ready for production use this is basically the beginning a full stack web development with with dotnet you can get blazer web assembly with the latest dotnet core SDK it shipped with version three one three hundred make sure that's the version you have if you're looking for it if you have a slightly older three 1s SDK just go ahead and download and install the the new one it also ships with Visual Studio 20 nineteen sixteen six and with Visual Studio for Mac 8.6 so if you have either of those then you've already got laser weapon assembly on the machine and you are ready to go now this release of laser web assembly comes loaded with features it supports dotnet standard 2.1 so you can reuse your existing don''t libraries both on the client and on the server do code-sharing share your model types or your validation logic your blazer webassembly apps can be hosted by asp.net core you know dotnet core app for that full stack web development experience or they can run completely standalone and be deployed as a static site we have built-in support for authentication using asp.net core identity with identity server which is a great open source project or you can use Azure ad as your ad b2c or an open ID connect provider of your choice I'm guessing we'll hear a lot more about that later this week we at Christy's talk you can build progressive web apps with laser and we're gonna be looking a lot more at that today you can debug your blazer webassembly apps both directly in the browser using the browser dev tools and also from visual studio or visual studio code we're working on also support in Visual Studio for Mac that should be coming later this year to read when your blazer web assembly app gets published we run an IL linker on the published output to remove any unused code should dramatically reduce the size of the application once it's published we also aggressively pre compress the publish tab to reduce its size even further we have support for configuration built in as well as globalization and localization support if you haven't got started with blazer yet you should it's really easy just go to blazer dotnet like I said you just need the dotnet core SDK previously there were extra steps to like install the blazer grab assembly template you no longer need to do that because Blazer web assembly is in the box with the dotnet core SDK you can then start developing your blazer app using Visual Studio Visual Studio for Mac or Visual Studio code with the c-sharp extension now that's blazer was always designed initially to for for building web applications plays a server and blazer web assembly are both just different ways of building apps using dotnet and c-sharp but in today what we want to do is actually start to go a little bit beyond that and take our web app that's you know happily running in a browser and start to give it more of a native app like feel so let's just start off we're going to take a look at progressive web apps now what is a progressive web app or PWA well a progressive web app is just a normal web app it just implements a number of additional open web standards that give it a more native app like feel now there are where there's a bunch of different aspects that PWA is but today we're going to look at three specific features of pwace first we'll look at making your web application installable using glaser we'll look at supporting offline execution and also supporting push notifications okay so installable what does that mean what does that mean to have a installable web application well install the web apps can be installed on various platforms so that they can be launched like a normal native app for example on a Windows machine you can launch a PWA that's been set up to be an installable from the Windows Start menu if you're on a phone or a tablet you can pin typically a PWA to like your home screen so that you can launch it directly from the home screen once once launched the web app there's still web apps and they're still running in a browser but they often will be given like a native shell so they look more like a native apps you lose the like you know the browser chrome with like the address bar and so forth and they can have their own icons and their own colors and so on there's basically three things you need in order to make your web application installable you're gonna need a web manifest which is just a JSON file with a bunch of metadata about your web application you need to support HTTP thank goodness a dotnet corn asp.net core support HTTP right out of the box and then you also need a serviceworker with a functional fad Chandler for your application and we'll talk a little bit more in just a second about what that that is and once you've got those three basic steps your app will be installable browsers can then detect that this is an installable app and they will offer to users to let them install the application like the user experience you see here from from from edge and there's lots of ways to also customize that experience so that you can have other in app installation flows to where you can like have an install button or advertise installation from your application now what is a Service Worker well a Service Worker is a script that the browser runs in the background separate from your web app they can serve a number of different functions but one of them is a service worker can act kind of like as a network proxy allowing you to control how requests are handled for your application now to use a Service Worker again you need to support HTTPS with your application and they are registered with your application as a as a script on page load now when the serviceworker starts running this is what they do they go through a life cycle the first step is the installation step if a serviceworker is registered when the app loads its install an event is raised so that the applicants so that the serviceworker has an opportunity to fetch the assets for the app and install them meaning to cache them locally on the user's machine they then go into an activated state so that that app the catta cache the installed app now becomes the actively running application now typically this is happening in the background so you load your app the install event occurs the assets get downloaded onto the to the machine and then that that's all happening while the user is already using the app and so often activation is going to happen for real later like after the the like the browser has been completely closed and then restarted once the serviceworker has been activated activation is also a good step by the way for where the serviceworker can look for a precast or preinstalled you can think of it that way versions of the app and clean those up once it's activated the service worker then goes into its normal flow of responsibilities of dealing with fetch requests with dealing with messages from the application and then the service worker may be terminated when it's no longer being used or due to memory pressure and another browser related concerns Daniel a couple of questions coming into the chat about with how do you update your app and does pre-rendering still work with a PWA so I don't know if those are in your next few slides but if you can try to address those questions I think the chat room appreciated yeah so that's actually a great question cuz I was just about to talk about about updates so the service if the browser detects that anything has changed with the Service Worker script like it when it fetches a new one and is even though like a bike difference from the previous script then that that Service Worker then goes through a similar flow gets a chance to install so it can it gets notified to install itself so we can fetch all the new assets for the application and you of course you want to do that as sort of an atomic unit like you don't want to have the app like partially installed so you have a weird mix of of assets so the install step will will kick off in the background with while the app is still running with the previous installed instance and if it's if everything downloads successfully and it succeeds only then will it then have the opportunity to go into the the activated State now I can't enter the activated state while the app is currently running look you already have the app executing typically so you have to like actually close all of the tabs with the the running application and then reopen and then the the new Service Worker will then have it's a activate event called so that has a chance to activate then it can go ahead and clear up all the old cache instances so that can kind of trip people up a little bit some people you might expect that you can deploy a new version of the application with the new Service Worker and then you just need to appeal refresh the browsing you're good to go right well not quite refreshing the browser will pull down the new Service Worker it will install but it can't actually activate until you close everything down and reopen it again so there's a there's one sort of period period of the browser life lifespan where the old app will still continue to run before the the new one actually kicks in that can catch some people by surprise it also means that you have to worry about your your app running potentially with multiple different client versions kicking around that's that's kind of the nature of this game as for pre-rendering I don't know off the top of my head of any reason why it wouldn't work but I'd have to go check into that pre-rendering with blazer webassembly in particular which is really what we're talking about here has its own set of complications because you now need to make sure your components can run both on the server and I'm on the client I have to look into that one I'm not actually sure off the top of my head thanks all right so let's that's sort of your basic intro to just getting your app installed well let's go take a look at how can we create an installable blazer PWA alright so like I said to get started plays or you're just going to want to go to a blazer net and that will take you here to the the blazer home page just click on get started follow the the Doc's to get your machine set up you just need the new SDK or if you have the latest version of Visual Studio or BS or Mac you're already set you're good to go I'm going to go ahead and pop up Visual Studio which I've already installed I'm going to create a new app then we're gonna select blazer app if you can't find it you can just search for it so search for blazer and there's at the top looks like next alright and let's create our first laser PW a good name okay and here are those two options that we talked about before this blazer server which is the server hosted version of blazer and blazer webassembly I'm gonna pick the blazer webassembly version because I want to build a PW a and then we have a few other options over here the right hand side let's take a look at the east so down here we have first of all the option to make this app asp.net core hosted if we do that then we will pair our blazer webassembly app with an asp.net core server that's that full stack offering if you leave this box unchecked then basically what you have now is a static site that you can deploy to a static site hosting solution like github pages or as your static site hosting this other option below is the option to create a PWA that this will add some additional assets to our application so that it supports PWA scenario so we're going to want to select both of those up above if you want you can also go into the authentication settings and enable authentication for your application we're gonna leave that for Chris to take care of tomorrow all right so let's go ahead and create this app so now Visual Studio is going to set up our solution for us remember I selected the ace but in asp.net core hosted options so we're actually going to end up with a multi project solution the client project which is what we see up top and the solutions Explorer that's our actual Blaser webassembly app and then the server project is the backend asp.net core server that's hosting our blazer web assembly app the client project builds the static files from that client project are then just hosted as normal static assets from the from the server project okay let's go ahead and just run this well let Visual Studio build and start up the server and host it and hopefully and just give it a second we'll should see a you know a simple single page app with our classic blazer purple gradient see if there's any questions while we're waiting any documentation for deploying blazer in SharePoint we don't have any documentation on that but I know there are some open source projects out there for like integrating blazer into SharePoint I think it's like blazer point or something like that is the name of the project if you're looking for community projects by the way like stuff done by the commute blazer I would point you to a ka dot ms slash awesome blazer okay aka dot MS / awesome blazer and that will bring you to github repo that's maintained by the community which has all sorts of cool stuff about blazer component libraries and drop libraries samples and icy shoes I don't know if laser pointers on here you see yeah laser pointers you might want to check out for using blazer with SharePoint ok here we got our app and you can see we've got some tabs we can click around we got the button that has a counter we've got a fetch data page which is pulling down some weather forecast data and rendering a simple little table pretty simple I'm sure many of you have probably seen this app demo domine about a hundred times ok but the interesting thing about this app is yet you'll notice that up at the top there's a little plus button that says install blazer this means that edge is detecting that this app is a PWA and that it is installable if i click that we then pop out of the browser and now we can see our web application in a like you know native shell it's got a nice native shell we've lost the browser chrome it still works it's the same same app same functionality no different this is still also running as a web application like it's it is basically a browser here it just it's been made to look like a native app if we go to the Start menu we can also see that our blazer PWA is now showing up in the Start menu and we can launch it from there and that would launch this there I just launched another instance so now we have two of them so you're getting that installable experience for this web application now how did we set that up let's go look at the project in the client project we basically gave you two things we gave you this manifest.json file you see that there that's the web manifest for this application and then below it we also gave you a serviceworker and I know some people kind of freak out when they see that javascript extension there there are some cases and Blaser I will admit where you do need to occasionally deal with JavaScript with service workers we it's mostly a recipe based approach you kind of implement the recipe and you're done so hopefully for the most part we've written this JavaScript for you but yeah sometimes you do need to deal with a little bit of JavaScript in Blaser we're working as much as we can to minimize that so here's the manifest and it just has some metadata about the app like its name how it should be displayed like should it be fullscreen should it be in its own chrome what its background color is and some icons so that when you install it you can customize how the icon shows up either on when you're pinning it to the homescreen or in the the Windows Start menu so we give you a little manifest and you can of course add add this this is just a this is not a blazer specific concept this is just an open web standard now the serviceworker if we open that it looks pretty bare-bones it's just got a very simple line of code here for dealing with fetch this is for development purposes it's not doing anything with like caching files or offline it's basically just acting as a pass-through proxy right now during development and that's so that you don't have to deal with caching issues while you're trying to update check make updates to your app there's another version of the serviceworker and this app that if we poke a little bit we can see it there's the published version a lot more going on that one we're gonna look we'll come back to that in just a sec now these files are both registered in the index dot HTML file so up at the top we can see there's the manifest so there's a link to the manifest file with the correct relationship and then down below there's just a little bit of script that's registering that serviceworker for this application so that it can then receive the the corresponding events and that's it and that sets up your app as an installable PWA right out of the box so there's still a couple questions coming in around caching and updates and things so in in the example you just showed there's actually a serviceworker that helps with cache busting so the development cycles fast and you don't have to worry about assets being cached where you might have made a change but there was a question around like controlling installation and what if there's a major update to the app if there's a major update the serviceworker should pick that up when you restart the app is that correct yeah well the the browser will pick up that there's a new Service Worker when you reload the the application so to check to see what the service worker the same as it was before yes no if it's not the same then the service worker gets a chance to install - to activate and it's in that installation logic where the service worker will pull in all the new assets for the app like if you did a major update it will pull in the completely new set of files catch them in a separate spot and then say yeah ok I succeeded I installed that all happens in the background while the old service workers version of the app is still running and then at that point it's waiting to activate and then when you've closed the app down that service worker then gets an opportunity to activate when the app loads again on activation it then switches to the to the new cache and all the old cache instance is typically get cleaned up well actually look at that in just a second so we'll see some of that code that's in the more that the published version of the service work implementation and there's another question I thought was interesting it says mr. smoothy asks is it possible to control if there is only one instance ever running so I'm thinking the question is probably around if we can we launched multiple instances of the app on our desktop and my gut reaction is that the app has no idea if other instances are running of the same application yeah not that I'm aware I mean you saw the obviously you can lunch two instances because I had two instances up whether you can like control for only one that I don't know I don't know if there's a way to do that yeah my guess is it's similar to opening two browser tabs they they're in a sandbox they don't really know about each other and I don't believe wrapping them in a PWA gives them any special ability to do anything different again I just want to also iterate that while we're showing how to do PWA is with blazer like the PWA set of technologies like service workers and manifests they're actually just open web standards so they're they're pretty they're agnostic to blazer or if you're using a JavaScript framework so a lot of this stuff is just you know the way the the functionality that browsers provide so let's let's talk now about the second feature which is offline execution which I think a lot of these questions are related to service workers can cache the app assets for offline use and you typically need to pick what strategy you want to use for that there's a number of different strategies like you could try to detect if the app is online or not and used the cache versions if you're not use don't go online if you are that tends to be a little unreliable because the the check first detecting if you're really really online can be a little flaky like maybe you're online but the network is just really terrible you know that type of situation so the caching strategy that we give you out of the box and Blaser is a cache first strategy if we have a cached version of the files then we'll use those if not then we'll go online and of course there's always that update check to see if like the new serviceworker has been installed so that a new cache can be established for data data you have to handle in the application yourself so like if you're pulling like we saw the weather forecast data there's nothing magic that will just cache the weather forecast data for you but in your application you can use things like local storage index DB to cache data locally and then implement a whatever synchronization strategy makes sense for your app now I'm off as you can kind of tell from the questions implementing support for offline in a web app is is non-trivial like there there are some interesting considerations that you need to think about we do have a fairly extensive dock in the blazer docks for all of the various nuances of dealing with offline and so I would point you to this link to check out those considerations if you're really just if you decide to to support this feature but let's go take a look at offline execution ok so minimize the browser so here's our app this is a PWA now wait I said that this app supports offline so let's try it I'm going to bring up the browser dev tools for this application members it is really a little browser that's hiding in this native Chrome and now let's go to the network and we're going to turn off the network so now this app has no access to the network anymore let's trigger a refresh and will this thing work well no it doesn't work and that's because like we saw before during development the app is using this sort of minimalistic serviceworker it's not actually even doing any caching for the published application though here's where the all the actual logic lives for for dealing with installing the app and we can take a look at this real quick so here's the uninstall event for the the serviceworker and this is using a assets manifest that we create when the app is built to figure out what are all the all the assets that make up this blazer app that that need to be cached you don't see it in the solution Explorer because it's produced on build but if we go poking around we can find it where is it it's like I think yeah so this serviceworker asset serviceworker assets j/s here's a list that we generate with hashes for every single asset that makes up the application so that assets file gets loaded by this serviceworker so it knows all the things that it needs to cache it does some some filtering to make sure it's not caching stuff that really shouldn't be cached or things that you you do want to make sure in addition that get cached and then crates the cache with a unique cache name and caches all those files all right so that's the uninstall event and then on activate this is where it goes through and deletes all the unused caches if this app was installed previously so it close down the browser the new service worker is ready to kick into gear cleans up it's it's after all its its buddies that were running it that had run before and sets up the the new cache and then on fetch this is the part that's intercepting each of those network requests and deciding to instead handle them using the the cached files so it's looking for example for whether there was actual full navigation or not this is a little trickier that's important you know like I said there's nuances to offline so make sure you check out the docs the doc is also linked up here at the top but what this is doing is well when you're caching a request to like say slash counter well slash counter actually uses client-side routing to to route to the counter component so really what you want is to render index.html like the route page and let that client-side router handle that that routed requests so when you're doing the caching logic you need to take that into account for navigating requests so that's what this logic is is doing otherwise for like other static assets like the DLL the webassembly runtime or whatever those can just be served from the cache if it's in the cache it uses it otherwise it makes a network request to pull down the new files okay so we want to use the this version of our serviceworker how can we do that well we need to publish the app so let's go ahead and right-click on our server project and we will select that we're going to publish this to file system it looks good then we'll go ahead and click publish we're probably those think we're publishing the server application so we're gonna publish the the back-end which will then have inside of it all of the static assets that make up the Blazer web assembly app then we can just run the the back end it will host the files for us and we can try out the the offline support alright so while that's going I'm gonna go ahead guys if I miss this Dan well while that's publishing the serviceworker j/s and the serviceworker publish j/s does the publish task switch that serviceworker out how does the dot published great question because now we have a little bit of msbuild magic like you can see it in the project file like there's this serviceworker item group that's saying like this is the serviceworker to include during development but when you're publishing please use this one then we have some msbuild logic that takes care of swapping when you actually run the the publish that is does that work with other types of publishing tasks or just the one within Visual Studio the publishing tasks are all run when you do like a dotnet publish from the command line so it's it's not vittles to your specific okay okay so we've got the app publish now we just gotta go open up command prompt and let's go find it I think it's it's in the bin release publish okay so somewhere in here and what's the name of the app let's blaze our app PW a server eggsy I think is what we want let's go ahead and get that up and running Windows is checking to make sure this file is safe no no what did I do unable to start Carol I probably have another oh yeah I've already using this so what's happening here is that the port 5,000 I have another app that's already using that port so I'm just gonna do a quick little trick which is I'm going to set an environment variable that's going to change the port for the application and I think I even have this in my demo steps yes this is what I want we'll switch it to sit for at 6000 there then by just doing that we should be now good to go there we go okay so now our app is running and let's pop up a new browser instance and browse to 6000 and one I think is what I need now okay it's a new new new port so it kind of looks like a new app we're gonna have to reinstall it which is fine alright so there's the app and now this one hopefully should work offline so let's bring up those browser dev tools and we will set the from online to offline and let's go ahead and do another refresh okay so that was like you know like loading the app anew and it just magically worked right like we have the app functioning without any network connection so this is now an offline functioning app now not everything works like we go to the fetch data page it's gonna try and make a network request to a back-end API and a camp because it doesn't have the network so data is something we still need to handle on our own now to show a little bit of that I actually have a different app which I'm going to switch to let me let me close this one down this is an app that we showed at the build conference and I make sure my back-end server is still running right it is this app is called card chucker yes and this app is supposed to be like an app that you would use if you're running a rental car company and you have an attendant who's supposed to handle cars being returns like the when you drive your car up into the parking lot and they check out the car see all the if there's any dings or scratches that you you added to the the cars look and take notes about that and then take them record the the gas model the gas and the mileage and all those types of things so it's a nice little app again it's a PWA all implemented in Blaser using blazer webassembly we can search for a car we get like nice nice autocomplete features like that's another one of those features that you normally would have to write with javascript but here that was all implemented with dotnet and c-sharp we can select a car I've got this cool sort of 3d visualization of the car we can see all the parts of the car that had notes taken about them before looks like this car has had a rough go like not a not an easy life not been treated gently you can like update the mileage and say it has now 45,000 miles if you put in something ridiculous it has forms and validation this is all implemented with blaze or webassembly we can we can change the amount of gas and so forth now this little 3d visualization you might wonder how that is implemented that's done with three J S which is a popular JavaScript 3d rendering library Blaser supports JavaScript Interop so you can call into existing JavaScript libraries if you want so this shows that if you have libraries that you want to reuse or libraries from the ecosystem you can still use them you're not shut off from the existing ecosystem questions coming in dan is the car checker app available on github yes it is so that is available at where doesn't make me I have a links all chat rooms already got it Marin from our support team there you go thank you sounder since github repo also is there any performance difference between a published blazer app whether it's PWA or not published blazer app at vs. when you're in development mode um not significant I don't think like in terms of the actual like runtime execution of the app there there is significant difference in terms of the load size of a blazer webassembly app so when you when you're developing your blazer webassembly up B we don't we want the development workflow to be as fast and iterative as possible so we don't run like the dotnet linker and pre-compression on the the built assets while you're in development so if you look at like the network trace for a blazer webassembly app during development it's if you can find where the asset we can't be cache the assets after first load but if you find it you'll be notice like like it's actually a little bit big you know five six megabytes for a default app and that's just because they haven't been pre compressed haven't been been linked when you then publish the app the il linker gets run all the unused code gets removed we you know broadly compress the app the highest setting to really shrink it down and it shrinks down to like you know 1.8 1.7 megabytes I think depending on how much you decide to strip out so load time performance definitely is different during development but of course during development it's usually right there on your machine anyway so not that not that big a deal but for runtime performance I don't know of any other significant difference oom if they can difference excellent okay so you can add notes to this car to say you know there's something else wrong let's say that they know the user returned it and they there's something wrong with this wheel so let's add a note which repair like might need to be replaced something like that and then you can add a photo Oh where'd I put my like photo oh yeah so this is the this is the car we oh yeah it looks like that might need some work and we'll save that and so now we have a new note we can that shows up with with the rest of the notes okay and we can save that data and so now that car has been updated if we go back to it it was the wrong one you can see that my note on the that wheel has been has been saved and that all works beautifully while this app is offline it is online if I switch it now to be offline f12 and we've to offline let's try refreshing the app just to see if the app functions yep works just fine it's about pulling for you can see the serviceworker is kicking in a bunch of cases to preserve the cached assets but also the data is available as well like we have like our our wheel is all there like we were able to pull in the we can search for cars that's because we've cashed all the the car data locally in this app using indexdb that's how that's working and if you try to make a change like that soon let's put something else in here like badly scratched save and if we try to save again you notice at the bottom the app detects that it couldn't sync to the server like the request to the server failed but it's storing locally the edits that it made so that the next time when the tenon is back in the back in with network coverage you know they're not right now they're out in the parking lot where they have terrible network coverage but they go back to the office and the network comes back online let's turn the network back online they can then retry the request and retry the request what did I do wrong here where my family's my server down no my server is up put it back to online well I'm not sure what I'm doing wrong there looks like it's all mine which refresh again - sings oh I wonder if the issue here is actually that my credential has expired there's a little I think there's a little issue with this app where it doesn't the the token expires and it does not refresh incorrectly let me see if I can log back in this app has full authentication which is kind of nice to see stealing a little bit of Christmas Thunder here this is a period there yep thank you now there's a question of the chat room but can you show that the user thought that offline and we saw the message to come up and they kind of caught that but is there an a built-in API for checking to see if somebody's offline is there like an event that we can hook into in Glaser or is that some JavaScript interrupts that we need there is an API they can use it is a JavaScript API Blaser doesn't provide any out-of-the-box wrapper for it in fact most of the stuff that you do in the Service Worker logic we don't try to do a c-sharp wrapper over those things just I mean you could imagine separately loading the dotnet webassembly runtime in a serviceworker and then writing your serviceworker code with c-sharp but typically the service workers are not like huge chunks of JavaScript they're fairly contained so we haven't bothered doing that so yeah you would just in your serviceworker code call the corresponding JavaScript API for checking whether you're online or not all right I'm gonna try this one more time because I think it was just a issue with my network connect my my sign-in connection so I had another note I'm offline right now broken save okay save again could not sink now we go online should be good let's retry and there we go okay yeah it was just a problem with my my login credential so yeah so that isn't now an app that is both supports offline execution and also supports offline handling of data locally in the app just to show you the code quit cuz I know we're getting short on time let me go - looks like Steve Sanderson's joined us in the chat room as well it's not I see have you Steve that's great pull up car checker here's the code for the car checker application now this is what you can find on the on Steve site you know thank you Steve for implementing this this this app for us let's give us a second to load John Gamble easier as well nice to have the dotnet folks joining us okay so if we look in car checker and we see that sort of standard solution structure right we have a server project which is the ace net core host and we have the client project with the application if we go looking in here we can see that on save let's see in the in the vehicle editor this is the page for when you're like adding edits to to the vehicle this has got a form and when the form is submitted with a valid submission where the data the data has been validated then we call this the save method which is down below so on the save method it uses the this vehicle store API in order to save the the vehicle data and that's actually going to store it locally in the using index DB let's go find that that data type so local vehicle store here it is and alright say so it's going to do it just a quick quick update doing this put a sink call which eventually is gonna bottom out at doing a little bit of JavaScript Interop again you know we said promise you know JavaScript JavaScript Interop but there is a little JavaScript Interop in this app to deal with indexeddb hopefully at some point we'll have a nice JavaScript Interop library from the community for doing that but Steven this app did it rolled his his little own implementation so in this ID bjs file not the load vehicle store or file this is the code that c-sharp code is in calling in to to handle all the interactions with indexdb and you can tell it's not it's not too bad it's got a little bit JavaScript for setting up the schema of the database and it's got like get get all put delete type of operations on the on the database store now that little synchronized widget that we saw at the bottom of the application that's implemented by this component when this component loads it tries to do a synchronization with with the server and it calls again into that local vehicle store a service in order to synchronize the data all the edits that have been saved locally in indexdb try to push them up to the server if that succeeds like if it doesn't throw an exception then you're good to go if it fails then it saves that the last sync failed and puts up a little bit of UI up above to say you know could not sink the the last edits and then gives you a retry button that you can use to to retry the request so that's the type of logic you would do to handle offline data alright let's talk about push notifications alright so the last feature I wanted to talk about with PW A's 10 minutes ok a little quicker push notifications are a way for web applications to notify the user even when the app is isn't running it's like an offline notification this is useful if you have like important events that you want to let the user know about for your application push notifications are kind of interesting the way they work in browsers they actually actually involve a hosted push service for sending the notification back to the browser the flow kind of looks like this in the browser you need to first subscribe the user to the the notification which involves asking for their permission so you can't just spam them with notifications without them saying it's ok you have to ask them if they give the permission then you can get a subscription for that user the subscription is just a bunch of tokens that to fire like yeah this user has said it's okay to send them these particular notifications you then send those that subscription to your apps back into usually to persist like you would put them in your database and then to handle and when you want to now send a notification to the user you use the push service for that particular browser now the each browser has their own and the exact endpoint that you're supposed to use depends on the browser that's that information is provided as part of the subscription but the interface for the push service is standardized and so how you send that API request that push request it's done in a standardized way the push service then handles sending the push event back to the the browser to the to the user and they get a notification on their on their machine so to set up push notifications you basically need three things you need to subscribe the user to the notifications with their permission you trigger the push notification then from your back-end based on whatever event is important like you know the pizza has been now been delivered and you want to let the user know and then you handle on your back-end sending the the push request to the push service which will then notify the browser and in your serviceworker you have to handle that push event to then show the notification to the user alright show this really quick so I have this Pizza store app if you haven't seen this app before it's really fun it's actually part of a workshop that we provide online you can go to a kms pizza' pizza store in this workshop you you build this entire pizza store over the course of like nine or ten labs it's a self-paced workshop yeah so if you haven't gone through this I highly recommend it's a great way to learn Blaser so I have the app here on my machine let's go ahead and start it up there we go let's gonna load up the server snaps kind of funny because it's all British Pizza in honor I think we first showed this in London and also it's it's kind of in honor of Steve Sanderson since he's also from the UK hello everyone from the from the UK okay so here's the the pizza store app let me just make sure that I haven't already granted permission for notifications looks like we haven't let me go ahead and order some pizza this is also a P okay so let's go ahead and let's order the Brit and then what I'm gonna do here let's uh let's get some pizza with duck sausage and maybe served on a silver platter because why not and some fresh fresh tomatoes okay great you know go big or go home right alright so that looks good it's big again let's go ahead and order that and I'm not logged in so let's go ahead and lock in okay now you notice I'm about to check it out for this pizza and the app is asking me hey do you the app wants to show you notifications are you okay with that so this is the push note that push notification flow kicking into gear where we are requesting a subscription for the notification so I'm gonna allow that alright and then let me go ahead and put in my just some dummy data here for the where to deliver it to and now we'll place the order all right we got a little status page that's showing where I am NOT it's not actually where I am but you know some some random place and I think in London and it takes a minute for the there so there's our notification everyone see that down at the bottom there's a pizza has been been dispatched so the driver is now on his way plowing through the streets of London I guess that's a you must be on like a helicopter or it's Jeremy Meads drone delivery delivering our pizza and then once the driver actually arrives we'll see another notification to say that the the pizza has been delivered okay I believe that location is the location of the first blazer workshop that may very well be the case I don't remember has it been that long okay so how do you how does that all being being set up so let's go to the check out component that's the component where I had ordered my pizza and I first saw that notification so in here you can see that when the check out component initializes it requests a notification subscription using some c-sharp code and again I know if I apologize there are Pizza just got delivered everyone see that and I can even click on this and the the app is set up as a PW way as well and it opens up the PD PW a locally on my machine so we can pull push notifications that's cool okay so that's the that's the app we have a little bit of JavaScript here that's setting up making the standard standard JavaScript calls to request the notifications subscription and we could go look a little bit of that javascript code but it's nothing too nothing too fancy like this is the the one call right here to request the subscription and it involves setting up like these keys there's some there's a little bit of some hoops you have to do in order to set up that subscription that's that's the there's a little bit of code there that you can check out in the workshop and then it makes a call to the back end of this app using this orders client just to pass that subscription to the server so that it can be stored if we go look at the server project we can find that in this notifications controller so here's that API endpoint we're calling this subscribe endpoint and this is just saving the subscription into the database and this has like those those tokens and the actual push service URL that we need to use for sending the notification to the user okay once an order has been made which we go back to the the application let's say was a checkout was where we're at so once we've placed an order it sends the order sorry it set it places the order to the server using the orders client again and that will make a call to this orders controller and call place order which is down here and in this method down at the bottom we can see that it's getting the notification subscription back out of the database and then calling a little creative a little task that will send those two push notifications back down to the to the client and here's the here's those two push notifications the one for the order being dispatched and the one for the order actually arriving this is all being handled on the the server how are those notification requests being made well here's the the code and you know and don't do this like don't put your keys and ink code this is just for for workshop you know learning purposes but actually sending those push requests to the first service is a little bit involved like there's some crypto stuff that you got to do fortunately this is Annette has a great ecosystem and there's a third-party library that you can use to send these push requests the library that we picked for this app what is it it's called let me bring up then you get package Explorer yeah this web push library is the one that we use for sending those requests and you can go check them out on github here's the URL for their library give them a star because they did a great job so we just use an existing dotnet library for for sending those requests but once those we'd is the request actually coming out of asp net core or is it using like a third party like a send grid or something like that so you can see right here like it's using this web push client and it's sending it to the using the push subscription to send it to the push service so it's going out from a snit core to some other endpoint that's browser specific does that make sense mm-hmm okay great so it sends the it tells the push service I want to now send a notification that this user gave me permission for here's my subscription and then the push service will then send the the push notification to the browser and we have to handle that client-side in our serviceworker so if we go look at the client app and go poke around in the serviceworker code you can see it also is registering a push eventlistener to handle actually showing the notification so that's where the notification actually shows up all right I know on that time but I'm gonna I'm gonna keep on going this is one more thing I want to show you like we we have been talking about going beyond the browser we started with building web apps with blazer server and blazer web assembly we then started making those apps have a more native-like feel by building a PWA that supported being installed offline execution push notifications but we've been talking for a while in blaze even early on in the project we knew we wanted blaze it to be about more than just web apps and it was designed with that in mind and we've been experiment experimenting with taking blazer from the web to actually supporting native like desktop and mobile applications for example you can imagine taking your web UI components that you've implemented in Blaser and putting them in the native app like a native mobile app or a desktop app and reusing those UI assets that's sort of a hybrid approach of a native app with hybrid web UI we call that blazer hybrid and you can even go further like Blazers component model is very flexible it's actually not coupled to how the pixels get drawn on the screen how they get rendered to typically what blazer you're rendering HTML and using CSS but the component model actually doesn't require that you can replace the the renderer with something else that renders to whatever you'd like like if you want to render to native UI controls of the machine you can do that using Blazers component model and we call that blazer native where you're not only implementing a full native blazer app but actually implementing even native UI not not even using web text for the UI and that's kind of nice because it means you get that native look and feel but you still get the familiarity of the Blazer programming model if you're coming from that background like you're a web developer and that's what you know and you want to used on it then you can use those skills to build a full native application now one of the we've done various experiments for blazer hybrid blazer native like we have we did a experiment early on try building electron apps with with blazer electrons basically like an embedded chromium browser shell with a with some code so you can build cross-platform desktop apps usually you do them in JavaScript with with laser you could do them with dotnet more recently we've also released this experimental project called the mobile blazer bindings which enables you to build fully native UI with the mobile blazer bindings you're running natively on the machine you're riding blazer components you're writing razor files but you're actually rendering to native UI controls yeah full access to the device and its capabilities full access to the dotnet ecosystem but using a familiar web programming model to build your app this is something available that's a for you to try out right right now and I can just let us show it to you real fast to give you a taste of how we hope to take blazer even further beyond the browser for supporting supporting even you know full native desktop app development ok I have another solution right here so this is a simple little app this is a mobile blazer binding app in this case now the mobile blazer bindings is a collaboration between us and the xamarin team so the underlying technology here is is xamarin forms and here's the main component for my little application I'll go ahead and run this so you can just see what it what it does here we're using the WPF bindings for xamarin forms so we're using abstract controls men are being mapped to WPF so we get a native desktop app but using the WPF rendering system and we get a counter like we always do with blazer of course right we've got a counter but this is a fully native app and the UI controls here are native controls like we're using WPF controls in this case for running the app you could also take the same code and compile it to run is like like a cocoa app on on a Mac or as a mobile app on Android or iOS using the same tech that xamarin forms uses but you can see we got to write this app with with razors like this is razor syntax these tags we're no longer looking at HTML these our components that wrap the underlying native controls like we have a Content view in a stack layout but it's all razor syntax so let me let me close down the previously and let's let's add some more razor in here like see if I can write for loop and equals zero I is less than 3 I plus plus I could do that right and where we went put in here let's put in another label component where the text is set to some thing that we're going to use C sharp for let's put just let's just put the count let's just book whatever that count is and to make the font bigger font size what do we have above 40 okay so this should generate three labels using normal razor logic let's rerun this app oh I forgot together to string this because it's gonna be a string not an integer text is a string of course and we run rerun the app and now we have 0 1 2 so we just created a bunch of labels using razor syntax so this is all native UI and this is what mobile blazer bindings offers today still can click on the count but what about hybrid like what if you have some web UI that you want to use in this native app like ideally you could just like start typing some HTML here like you know h2 hi I'm web UI right you can't do that because this is this is not you know this is this this this is based on these native controls not on HTML but what if you had a another control that's a blazer webview so it's a webview that allows you to render some some web UI within your native application what else could we put in here like I'm gonna put a LP tag this is cool right perfect okay so we got some simple HTML let's run it again so hopefully this what this webview is is just a control that wraps the browser control from 0 forums and now we're rendering some web UI inside of our native desktop application it'll click count alright but it's not just a webview like it's a blazer webview right so we should be able to put some c-sharp logic in here so let's do this let's say that for the header er the current count is and we'll just render the same value that we have above and then let's turn this into a button it's a lower case B and let's say it will be count and then let's use the same onclick handler that we used in the native part of the UI but now we're going to do it with web UI and we have to use the web version of this because we had a register a web event I think that looks right and let's rerun the app now it's tied to the same state in both the native UI you notice it's using this counter state current count and in the web UI part it's using that same state so when I click the count above it updates the counter in both the native UI part of the app and in the blazer webview part of the app and both both count buttons work exactly the same so we can do blazer stuff inside of this blazer webview and in fact in this app we have the entire default blazer application tucked away in here and it's referenced by this this app let me just grab the little snippet for setting that up oh yeah this is what we want okay so instead of this blazer webview I'm not putting this one and here what we're doing is we're rendering the route app component for the default blazer template entirely within a native application so let's try running that little blazer inception huh yes yes all right cool so now we've got like the entire default blazer app running inside of our WPF application and the counter is wired up to the same state so it can click on the counter and it works the same way as we as we saw before so this is kind of cool this means that if I have like existing web UI that I want to reuse from my cross-platform native application I can I can do that and so it's the last demo I wanted to show is we actually have the entire car collector application here and let me set this as the start project that now hosted inside of a mobile blazer bindings based application and go ahead and run that now since this application is running on the desktop we're getting of the full dotnet framework not the mono dot woz inversion exactly so there's no web assembly in this app like this is a this is a native app and it's running using a dotnet runtime that's native to the machine it's not it's not using a web assembly runtime tucked in a browser and then we're just talking to the browser controlled in order to render the pixels so this is the same set of components but it's now running with you get all the performance of the native platform you also get its capabilities so let's just show that the app still works like we can like search for a car and do JavaScript Interop and got our 3d thing but we can do more that stuff that we couldn't do from a browser like down here below Steve was kind enough to add a open report button let me actually get a car that has some some issues I think this one yeah this one's got some issues on the bottom okay so we've got some notes for this car and there's a button here for generating like exporting the data for this particular car now if we click on that we just opened notepad from our application that's not something you can do from a browser app because this is a native application using native data at runtime we have access to those capabilities of the device so this is something that we're working on the mobile will the Blazer webview is not currently public but it's something we're working on with the the xamarin folks to make part of the mobile blazer bindings and we hope we'll have something there to share soon yeah this will be really interesting for us when it's published to see how if we put a teller qi4 blazer data grid inside of xamarin shell and how to interact with OS and all those types of things would be interesting scenario yeah so just that's that's what I had to show today in summary you can now build full stack web apps with blazer using dotnet and c-sharp both blazer server and blazer web assembly have been released and they're ready for production use you can build progressive web apps we place our web assembly installable they can run offline they can handle push notifications they can do anything that a modern web app can do and we also encourage you to try out some of the experiments that we've been doing with native apps using blazer especially the experimental mobile blazer bindings here's a linked list of resource links from the various things that I showed today of course go to the Blazer done at homepage and install the bits we have lots of Doc's you can find the car checker app online as well as the pizza store app and the there's the link for learning more about the mobile player bindings and with that I encourage you to try out blazer today and I'm happy to stick around for just a few minutes and answer some questions so we had a couple questions come in one of them was about I think it's more of a terminology thing is blazer mobile bindings Maui how is it related to Maui some people may have noticed that that Maui showed up in that that demo if you haven't heard of dotnet Maui don''t Maui is our effort to create a cross-platform UI stack for for.net it's happening being worked on for the.net donna v dot net six wave and it is basically taking xamarin forms and rebranding it and broadening it to support more scenarios and more programming paradigms so it's it's it's fundamentally based still on the xamarin forms tec with the mobile blades that laser bindings we're taking xamarin forms and experimenting with how could we create an experience that's more appealing to web developers and we expect that those investigations will accrue to to maui that in addition to being able to write maui up using sam'l or using the new like plain plain old c-sharp program model that they're working on I imagine you could also choose to build your Maui app using a more web like programming model including hybrid scenarios using Blaser that's something that we're investigating with them and hopefully we'll have more to share on that in the future the next question is about Microsoft power apps in how that relates to the development of maui and blade in these type of things um powerup supports dotnet that's about my extent of my knowledge unfortunately I know you can do a bunch of dotnet stuff with power apps I think there was some we've had some some discussions with them about enabling like a blazer based extensibility model for power apps that might might be interesting to to look at but nothing nothing official nothing really to share they're not really aware of any other overlap I think my general take on it is please correct me if I'm wrong the blade the Microsoft power apps is like a low code environment type of thing where you know the Maui and blazer you're building an entire app from scratch you know you've got a team of developers that type of thing they're kind of two different audiences that you know if you picture like a vein diagram like they cross over in the middle somewhere but they're different tools for different different developer audiences is that about right that is thatis true in terms of their core scenarios like power apps is for like citizen developer type type of scenarios really easy way to create quick rapid rapid development of applications but they do have like an extensibility model and when you get into the extensibility model you start getting to more of the professional dev type of scenarios that we typically deal with with a spinette core and blazer and so you could imagine you know maybe blazer could have a role to play if you wanted to extend your power wrap in some way with the help of some professional devs and you want it to do that using using.net but like I said that's all just like really early thinking and discussions and brainstorming don't know if anything will come with that I think I think that was more the answer folks who are looking for appreciate that DN I especially want to say thank you for Dan and your team for coming out and helping us with the session today it looks like everybody's really enjoyed the content there's a lot of good chatter here at the end about everybody really just enjoying the session in general so thank you very much we've got lots of content planned for the rest of the week as well so we've got Chris ante joining us tomorrow to talk about authentication so him and I are gonna dive into authentication a little bit and see what we can do there there's some really cool components that are baked into the framework now that let us do trade out views for different roles and things like that so we're gonna take a look at some of that stuff tomorrow we've got I'll be on c-sharp fridges Fritz's channel on twitch on Friday and we're gonna look at some of the new get packages that we talked about today so we we talked a little bit about like awesome blazer and looked at some of the list of things there we're gonna do the same thing in depth on Friday so we're gonna dig in for about two hours and try some of those things out kick the tires on a couple of them maybe highlight some of the our favorites and things like that so we've got a lot more content plan this week you can catch that at tinyurl.com blazoning - summer or just follow the channel here at codit live and follow c-sharp Fritz's channel as well for friday and yes those will start at the same time 11 o'clock Eastern Standard Time for those and it looks like we're going to be giving away some prizes here as we close out the show so we're gonna have some prizes coming up here not sure with what the team is going to do as far as picking numbers they they like to ask our our hosts and and me as well to pick numbers oops got the wrong slides up here trying to get to some closing notes here ignore the man behind the curtain here we go so some some more resources for you all telluric UI for Blazers in full release you can grab that at Telecom slash blazer UI we've got a brand new demo app up there called blazing coffee which is really cool something I've been working hard on for the last couple weeks we've got crud operations and server-side sorting paging filtering operations there is it's a PWA app has some really cool theming capabilities that you probably haven't seen in any blazer apps yet so make sure you check that out links are up on the screen here fiddler is also a great companion it's free it's absolutely free download from us that helps you build any dotnet app that's got a API back-end on it which is pretty much everything these days so you can inspect your HTTP traffic and all that good stuff and we've got some links to some more dot doc stop microsoft comm stuff in here as well so make sure you take a quick screenshot of that slide and then later today at one o'clock on this channel we've got TJ van tol coming on to talk about state management with react and you may think that doesn't pertain the Blazer but actually a lot of this the patterns of that type of thing translate over to blazer as well so I want to just check that out to poach some ideas we may have been heavily inspired by by yeah there's some great libraries out there as well in the dotnet ecosystem that mimic these state management libraries from react to so you can pick up some tips there with TJ at one o'clock and 2:30 Alissa's oh this is yeah 2:30 today Alyssa is going to talk about some web design stuff so make sure you keep tuned to the channel the rest of the day here at code it live and with that let's check on the prize situation so let's see what we have going on for prizes Dan if you can pick four numbers between one and 126 we're using the Dan Daniel Roth random number as a service for her X rises today soon I assume they need to be integers by the way just yeah they should be whole numbers whole numbers whole numbers okay okay we're gonna go with 317 because I think that's the number of Blaser webassembly previews we shipped before we actually got to the final release 111 and I can't decide 126 126 the last one or does have to be between it do I have to go one more is that is that as I'm off by one error no I think 126 should be valid okay okay didn't want to like overflow the buffer so if you all didn't catch the show yesterday we should have it up on YouTube soon maybe the team here Sarah if somebody can comment if we've got that YouTube video up yet we talked about like full stack dotnet yesterday it was really a fun session to give we have blazer web assembly on the front end I've got the app up now that we talked about so if you want to see more details about this app check out the session from yesterday we have blazer webOS Emily on the front end net wavy API web api on the back end and full authentication involved here PWA app as well and we have a demo on a nice dashboard like this where you can do server-side paging and sorting and filtering so what we do is we package up all of the grids state data and we've shipped that off to the Web API back-end and then there is a one line piece of magic that our engineers made that converts all of the grid state into an entity framework set of expression trees and it just takes that and turns it into a sequel code and you get only the page of data that you need based on that filter criteria back you're saving a lot of data processing on the server side and then you're only shipping a small payload across the wire and only rendering what you need in the browser so there's some really cool efficiencies there and then we also have a demo in our data grid on how to do create read update delete operations within Blaser and within the data grid itself and one of the really cool things that's in here it's kind of a little hidden gem is you can click Edit on one of these items and in the nutrition information you'll see a telluric file upload button so you can click select files you can grab a do CX file so an office document and upload that to the server our telluric libraries also include a document processing library so when that file it gets uploaded the Web API accepts the file and then runs it through our document processing libraries and actually converts that into a PDF on the fly and saves it to disk as a PDF so now if I reopen the grid that's refreshed we have the PDF right there in the browser from the converted do CX file so this app did I when I wrote this it spent the last couple weeks putting it together one of the easiest apps that I've written in a long time because I was able to use dotnet full stack it's one of those things where when I write the code it just works and it works as expected so I think that a lot of the credit goes to the fact that the framework just is so intuitive to use it's nice to be able to just do one language one framework and just reuse those skills like you get get that sort of a accruing value for everything you know which is pace forward and your front-end development there's one more little hidden gem in here too this is not blazer related Dan but this is a real fun one so we have really extensive theming capabilities so themes are really easy to use in in our components and integrate those with any laser app so if I go into my system theme settings so I'm gonna go into my OS theme settings and I'm gonna choose my color scheme and Windows 10 has a dark and light color scheme now I'm gonna switch over to the light color scheme real quick and my app actually just responds immediately to that new color scheme so there's a set of media queries that you can put on your CSS files now that check the OS preferred theme setting you can just sniff that media query and if it's if your preferred theme is dark you can load a completely separate CSS theme into your application that's cool it just does it for you it's like magic I love it and it requires zero code there's actually no code required to run that so there's actually just a media query that you attach if I do inspect here and we need to get out of the tablet mode here let's do inspect again I think it's it's hiding here at the bottom of the screen there we go if I go up into the head part of my app you'll see there's two CSS files in here and one has a media property or actually both have a media property but one has a media property that says prefers color scheme light or no preference and the other one is prefers color scheme dark and there's literally not a single line of JavaScript or C sharp code running that it it's a browser feature and since we're using web standard tech it just does what it's supposed to do very nice all right Daniel thank you very much again for joining us today I think we've given away our prizes do you have any parting thoughts or comments or things that you like to share well just thank you everyone for attending today I hope you found it useful and I hope you enjoy building your next web app the plays are awesome thanks so much Dan just gonna check on my team one more time Sarah are we good to go just make sure we got the thumbs up to sign off make sure they don't have any more prizes to give away or housekeeping to do all right so I don't see anything coming over so thanks again and thanks to Steve Sanderson for coming in to chat and I saw John Galloway in there as well so definitely appreciate appreciate the Microsoft folks for showing up and then thank you for the hundreds of viewers that showed up today too without you guys there would be no show so thanks again and take care everybody we'll see you tomorrow with Chris ante same time same place and have a good day bye everyone
Info
Channel: Progress Telerik
Views: 1,246
Rating: 4.8400002 out of 5
Keywords: Telerik, blazor, progressive web apps, pwa, blazor ui library, telerik for blazor, asp.net, asp net, .net, net, microsoft, CodeItLive, twitch, stream, irl, web development, software development, c#, csharp
Id: 9EhZvYfRfF4
Channel Id: undefined
Length: 85min 28sec (5128 seconds)
Published: Thu Jun 04 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.