Blazor, a new framework for browser-based .NET apps - Steve Sanderson

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Absolutely amazing talk.

  • 00:00 - 11:00: Talks about basic Blazor stuff previously known.
  • 11:00 - 17:35: Shows binding to make a kind of dividing bar like on Humble Bundle.
  • 17:35 - 31:15: Makes a product scanner "Blazor Mart" with Blazor + gRPC.
  • 31:15 - 43:00: Test driven development to implement 'remove item' functionality.
  • 43:00 - 48:00: Makes it a PWA by adding a service worker for temporary offline use.
  • 48:00 - 49:50: Makes the web app installable in your OS (again, PWA).
  • 49:50 - end: Talks about Server-side vs WebAssembly, 'Hybrid Blazor' (Electron). Shows of the beginning of 'Blazor + Native UI' for native mobile and desktop applications (no release date announced).

Slides and code at https://aka.ms/sanderson-london-2020.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/RobbeSch πŸ“…οΈŽ︎ Feb 15 2020 πŸ—«︎ replies

Very nice content, I am falling in love again with .net core, the future for this technology looks pretty promising.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/heavykick89 πŸ“…οΈŽ︎ Feb 15 2020 πŸ—«︎ replies

That was a great talk! However, the end on native iOS was a bit reminiscent of dreaded WPF tags and binding :)

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/viboux πŸ“…οΈŽ︎ Feb 15 2020 πŸ—«︎ replies

The best hour one minute and twelve seconds I've spent in a very long time. I'm very excited about Blazor. This is awesome.

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/the_other_sam πŸ“…οΈŽ︎ Feb 15 2020 πŸ—«︎ replies

Can anyone tell me how he runs Blazor Web Assembly and seems to make changes in the razor files and have it instantly reflected in the browser side? I have tried many different build options and have never gotten anything that has looked that smooth.

I know they are planning to do hot reloading but haven't heard any kind of update on it. Which I don't think he is using here.

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/Insight54 πŸ“…οΈŽ︎ Feb 16 2020 πŸ—«︎ replies
Captions
ah the screen is on and you can hear me fantastic okay people will keep coming in for a minute but I'll probably get started and so hello everyone nice to see you thank you for coming here I hope this is going to be a fun way to end the first day of the conference for you so my name is Steve and I work on this thing this blazer product so I'm on the asp net team at Microsoft and we've been developing blazer for a couple of years now and it's kind of released and kind of not released but we'll talk more about that in a minute just so I can tailor my introduction to you a little bit can you do our quick hands up if you feel that you know what blazer is about like you've heard the big idea like okay so almost everyone alright um and also for my personal interests hands up if you've actually used it or tried it out in any way that's alright that's pretty much half of the people here so that's pretty cool so it's becoming a little bit tricky to decide how to do talks about blazer because we're at the point now where so many people know about the basics that you can't really just do a whole talk about that but at the same time there's still quite a lot of people that need to catch up so the kind of middle ground that I want to strike in this talk to set your expectations is for about the first 15 minutes or so 10 to 15 minutes we're going to go through some of the basic ideas like what's the point of this thing why does it exist what does it look like what can you do with it and we'll do a bit of programming in some simple cases and then after that for the remaining part of the talk we'll go into some more advanced scenarios and we'll look at some future things that we haven't actually shipped yet some cool experimental things that we're working towards so you can get a sense of where this is going so to start off with this little intro section let me give you a quick history lesson so I want you to think back in time cast your minds back like as far as you can possibly remember your earliest memories it's like 2017 or there abouts and think about what it was like back then back in those days if you were trying to make a rich web application show up in someone's browser well if you wanted it to be interactive in any way you would have to use one of these things so you'd be using something like angular or react or view and you would be building what is basically a JavaScript application and maybe you think well yeah my code wasn't actually JavaScript back then and was using typescript or flow or something else well yeah that's cool but that does compile to JavaScript so at runtime the semantics of your application are JavaScript and that's just the way things were and that's fine people were very successful and they're led happy and fulfilled lives with that but it's kind of a shame if the only language that you can use is just one thing cuz you know software is a rich world we've got many different kinds of languages frameworks tool chains and the web would be a richer place if there were more options available and so that's why this exciting little thing came onto the scene at the start of 2017 which is webassembly a bytecode format for the web so it's a new type of code that can run in a browser it's not JavaScript it's a kind of byte code that you can compile to from whatever sort of language or ecosystem you want as long as you can compile to web assembly you can run inside the browser so back then at the start of 2017 when this was happening quite a lot of people started getting excited with ideas like well does this mean that we could run dotnet inside a browser again but this time without any sort of plugins just in a pure standards-compliant way and I was one of the people who got very excited about that I started doing some prototyping and I thought actually yeah there is a way that we can do this we can make applications run inside a browser we need three ingredients to make this work and the ingredients are one web assembly which is great because we've got that in fact we've had that for you know two to three years now this has been shipping a standard in all up-to-date browsers both desktop and mobile so that's basically a solved problem the next thing we need is some kind of dotnet runtime so what I found to my surprise and delight that without very much work it was possible to compile a dotnet runtime to web assembly and once you've done that you can load normal dotnet assemblies into it and execute them inside your browser which is amazing if the only thing you want to do is print messages to the console which is not exactly what I wanted to do I had slightly broader aspirations that I wanted to build actual rich you eyes and so that needed a UI framework and that's where this thing comes in blazer so blazer is a UI framework for dotnet it's not the ability to run dotnet on web assembly that's a separate thing blazer is a UI framework and it can run on web assembly but it can run in other places too so if you are running in a browser and web assembly then because you're already there in the browser you can build a UI just by having blazed a call-out to the Dom API for you and that's just gonna work and this is the original hosting model for blazer it's called client-side blazer or blazer webassembly as we call it now that's the original type of blazer but it's not the only type because while we were doing this we realize that we've got something pretty flexible here and we can run your blazer applications in other ways as well so another thing that we could do is we could take your blazer components and we could run them on a server in a cloud somewhere and then when they want to render some UI into someone's browser well they can reach out across the Internet through a real-time WebSocket signal our connection and cause the UI to appear there inside people's browsers and that is server-side laser so we're going to be talking a little bit more in this talk about the differences between these two models and why you should pick one or the other depending on your situation but before we really get to that I want to start looking at some code cuz we haven't done any coding yet and I've had enough for some slides so let's have a go at building an actual UI using the blazer programming model and the scenario I want to take on is budget allocation okay sounds unbelievably boring but imagine the situation right the situation is this next week you go back to your company and you adopt blazer and as an immediate result of that you inevitably become dramatically more successful okay and then following on from that is a another immediate result you have loads more money than you ever did before which is one of the problems there you know we can all relate to and so we have to decide then what we're going to do with all this extra money we need to somehow give it out to all the staff as bonuses but who gets the bonuses how much do they get well that's the budget allocation problem that we're going to solve and there are this is a real-world problem people try to build you eyes to do this kind of thing and an example of a real world ui4 budget allocation is this so I got this picture off the internet it's it's the humble jumbo bundle three just a snappy name and when you buy that you get to choose how your money gets distributed across these different budget items so how about we try and build something like that using the blazer programming model just now and then we'll get a sense of what it's like to use so I'm going to switch over to my IDE and you can see I'm using Visual Studio and when there's windows here but you don't have to do that you can equally well use vs code on Linux or Mac or and windows if you want you can use vs for Mac if you like and I'm just gonna use vo some windows because I'm familiar with that and this is my application I'm gonna start it up first and then we'll look at a little bit of the code inside there so if I run it you'll see this may be familiar to many of you certainly those of you who have seen blazer before this is pretty much the default file new project that you get when you create a new blazer project and it's got a few pages in there it's got some example stuff like at this button that you can click on and it counts it an example affecting some data from the server and that's very well but it's kind of boring and I don't want to talk about it too much because I've talked about a million times and you can see plenty of information about this on the internet already so what I want us to look at really is this bonus splitter page that we're going to implement so where's the code for that then well this is the project here and let's get the hang on that way all right so this is a blazer application in this case it's a blazer server application so my code here is going to be running on the server and it's going to be updating the UI dynamically over a socket connection but you won't really be able to tell that's happening because it's very fast but the same code would work equally well on blazer webassembly doesn't really make much difference now what have we got in here what is the code well it's a bunch of c-sharp files and RAZR files so razor files are the components in a blazer application and blazer is a component UI framework you build a set of components that contain other components it's just a big tree of components all the way down and the one we want to work on is this bonus dot razor and you can see doesn't have very much in there right now the only interesting thing really we've got is this page directive says this is the thing that will be displayed if you are at the URL bois de bonus and that is indeed the URL that I map so that's why that markup is getting displayed okay so let's put some logic in here now because this is a razor file I can put in some c-sharp code that will run wherever my application is running and I want to model the idea of this this budget situation so what we gonna do well let's start by defining the total amount of money that we're trying to allocate and we're gonna say we'll have a million pounds that we need to give out dollars or whatever units of currency you like and I need to know who are the candidates for receiving this money so I've defined this class called budget item which has got a name and an amount and we're going to set up a list of them so we can model our scenario okay so we want to give some money to developers some to managers and some to salespeople and now I can use that to write a little bit of UI so up here in my razor markup I can start writing out some normal HTML so I'm never div with class equals budget and if I want to make a list of things well I can use a normal C sharp for each statement so for each of our item in budget items we can omit some markup to those and the markup that I'm going to omit is going to look like this so for each thing I'm gonna display the name and the amount of money which is formatted as currency with zero decimal places and then we'll just have this little to-do message over here so let's run that now and see if that actually does render something so we reload and yes okay can you still hear me okay yeah okay sounds weird to me up here right so we can see we've got these three categories now developers managers and sales they've got no money and we need to make an editor and the kind of editor that we want to make if you remember looks like this so we want to have these horizontal sliders and the way we can do sliders in HTML is to use the input type equals range input type equals range and if you want to use one of these it starts at zero and you need to specify a maximum value that it goes up to and I'm going to goes up to the total budget we can also specify the minimum increments step so we don't need to go up in individual pounds or fractions of pounds honestly we've got so much money now we don't care about any unit that's less than a thousand pounds at a time and then finally we need to put this data somewhere so I'm gonna use Blazers built-in bind to set up a two-way binding between this slider and the amount that's on my item like that okay let's try that out and see if we built a nice budget editor okay so we've got these sliders and it does actually update the values on our underlying model which is cool but it's not very cool just yet actually it's pretty awful right now it's nearly impossible to enter any specific amount of money because you see that the numbers don't even update until I release the mouse so that's pretty terrible why is that well that is because Blazer is built on normal web technologies and let the bind attribute here that is by default connected to the browser's change event on that element and if you know web programming you may know that the change event will only fire when the user moves away from the component or when they let go of their mouse on a slider so that's not the event I want to listen to I want to listen to a different event which is standard in the browser and I can do that by saying the bind event I want to listen for is on input okay so let's see what effect that has now on the UI so now as I move these sliders you'll see that the number now updates in real time which is a lot better but we still got a series of UX problems with this but one of them is how do I know when I've allocated all the money like I maybe I don't know whether that adds up to a million or not my my arithmetic is not that good so let's display the amount of money that remains to be allocated and we can do this quite easily so NC shop we can define a property called remaining and we'll compute that by starting with the total budget and we'll subtract the sum of all the items that we've assigned so far and then we can display that on the screen inside a span like this the remaining amount is that formatted as a currency okay let's see if that makes things a little better now so we've got a million remaining and as we move this that amount goes down so that's pretty good but we've still got more problems for example nothing stops our user right now allocating even more money than they've actually got like I've done yeah so how can I stop them from doing that make sure they don't over spend their budget well I want to change the maximum value that you're allowed to assign and what I'm going to say is for each item you are allowed to assign the the amount that you have already assigned to that Plus at most the remaining amount okay hopefully that makes sense you've already got this much and this is how much is remaining maximally when you are editing this particular thing so let's see the effect of that now and I warn you it's pretty weird at this point so let's see I'm gonna give quite a lot of money to developers because obviously they're great and then I'll start assigning some money to the managers and watch what happens okay so if I move it right up to the end well okay so it's good in the sense that I wasn't able to exceed my budget anymore and I fact I can't even assign any money to the salespeople now because you know there's nothing left but it's also like mad because these two sliders they appear to be in the same place so you'd think they represent the same amount of money but they don't they represent different amounts because the scale factors have changed now depending on how I edited it so what I'm going to do is a cool little trick which is maybe hard to understand at first but just go with me I want to change the horizontal scale of these elements so that they compensates for the different max values that I'm assigning to them so don't worry if you don't quite follow this code you can think about it later and ponder on the maths behind it it's not too bad so we're saying the width of each item is going to be in proportion to the maximum amount that could be on that item so even if you don't quite follow that hopefully you'll appreciate the effect let's see what happens now so as I move the developers amount you'll see that the remaining space on the other ones goes down now to compensate for it so if there's only a small amount of money left there's only a very small slider that I can set up for the sales people which is cool and I quite like this as a UX because it really makes you think carefully about what you're doing so if you decide that you need to give more money to one group you have to think first about where you're taking it away from so in this case I would say well you know these people at the bottom they're not really adding any value so let's move that down there and then you know we can put it where it where it belongs okay that's good so we've made a pretty decent little user experience here but there's still one problem left at least maybe several but at least one and that's why if our user is not being very smart today and they just don't even allocate all the money and they're just leaving some money on the table for no reason at all how can we stop them from doing that well let's say that we want to have a Save button at the bottom of our UI so I'm gonna have a button with the captions save and I'm not gonna wire up any behavior to it but what I will say is that this button will be disabled if the remaining amount is greater than zero it's a very simple and intuitive way of controlling the state of that button come back and reload and you'll see that the Save button is disabled right now but if I allocate all the money then it becomes enabled disabled enabled disabled enabled and we've hopefully achieved our goals there so we've created something that's quite a lot like this real world example and we've done so in pretty straightforward and intuitive code not very much code the only difficult bit about is this weird expression on style there so I hope that gives you a sense of what the Blazer programming model looks like and how it allows you to combine normal HTML normal Dom type features with some c-sharp and then we can run that wherever we want whether it's on the server or whether it's inside web assembly the other bit about blazer that I've not really got into just yet is the fact that it's a component based framework so we've only been working on this one component and we're not really showing you how we can split stuff up into lots of components and reuse them from each other and to do that I want to move on to a slightly bigger a more interesting example so that previous application was running on blazer server and now want to move on to a bigger scenario that's going to be running on blazer webassembly and as we do that I'll show you some cool features that are not actually part of the framework yeah but things that we're thinking about including in the future and hopefully you can give us some feedback about so what will the scenario be well I thought it would be quite fun to do some things that doesn't actually even run inside a normal computer at all something that doesn't run inside a normal browser I would like to do something that runs on a specialized bit of hardware just for a change and the scenario that came to mind for me was this so how many of you have ever used one of these devices in your actual lives yeah so they're not that unusual they've been around for a few years now this photo is from Waitrose but I think I've already also seen them in ASDA so don't worry it's not just a middle-class thing you can even use them if you're from up north like me and if you're not familiar with this the way it works is you go into the supermarket and you're going to do some shopping but you're an impatient person and you don't want to go to the checkout at the end because standing in line is just the worst thing that you can do so what happens instead is you go into the supermarket and near the entrance you see this big Bank of devices and you walk over and you pick one of them up and it turns on and then while you're going around the supermarket doing your shopping each time you want to buy something you scan its barcode with your scanner and the device displays a list of items that are in your trolley right now and it shows you the price the amount that you spent altogether and then when you finish doing your shopping and you're ready to go home you don't have to go and stand in line and wait for someone to scan all your stuff all you do now is you go over to the payment area and you scan your order onto the payment machine you put your card in you pay and you walk out and you didn't have to queue up so that's that's the scenario and what we're gonna do in the next 20 minutes or so is build some of the UI that would run on one of these devices and hopefully as we go I'll be able to give you a few reasons why blazer webassembly would actually be a really good fit for this in the real world okay so let's switch over to the application that we're going to be working on now obviously we don't have time to build that completely from scratch right now so I've already started preparing a starting point for us here and what have I got in this solution then well I've got three projects in here but ignore the test one for now we'll get to that later we've got the server to client I'm just gonna start up my serve and I know that's kind of hard to to make sense of but there we go alright so the server in this case is the thing that's responsible for having all the product inventory data so there's too much data for us to actually put on one of these little devices so there's going to be some kind of back-end server that our client application to make requests to to get information about whatever Goods the user has scanned and that can be updated you know whenever we want now as it happens I've implemented it with a subpoena core but I didn't have to I could have used any server-side technology we want for that because Blaser as a client doesn't really care what your server is but you know I'm kind of familiar with it's been at core so that's why I've chosen to do that and then I've also got blazer client and this is a blazer webassembly application and inside there we've got basically the same stuff that we had in our other application which was running on the server so we've got the same kind of razor files and c-sharp files and inside there we're going to be doing the same component or intent programming so let's just try starting this up and see what it looks like before we look at some code so if I launch that in my browser now you'll see we get this blazer Mart and it's ready to go so I user can now start using it now if you remember in the real world the display will probably be sort of a portrait orientation like this or something but we don't really care about that that's just a matter of CSS so for the rest of this talk will just continue displaying it full screen in landscape mode and as you can see the only feature of our application that we want to expose to users is the ability to scan groceries now I've also got this autocomplete thing that I'll show you later but we wouldn't have that in the real world in the real world users are just going to be using a barcode scanner so to get a sense of what that's actually like I've got a barcode scanner and I've got some groceries such as this tin of beans so if I scan the barcode on this beans you can see that immediately my application jumps into life and it says ok you've scanned something and it's started to work but it's not really working correctly yeah you can see it says fake product instead of telling me what I actually scanned and so how does any of this work let's see some of the code that's behind there and I'd say the best place to start with understanding this is this component that I've created called appraiser that's my top level root component in this application and if we look in there you'll see that we've got a series of other things so up at the top we've got this search box that's obviously corresponds to the thing up there on the screen and then below that we're doing the same thing that we did in the budget example where we're using a normal for each loop to say for each of the things in your cart we're going to display this other component that I've created called cart row display and then below that if there's anything in your cart will display a footer so you may remember that initially there was nothing in my car and I didn't have any footer on the screen and so this if test was false but when I come along and I scan something then that test will become true and the item will become part of the UI okay pretty straightforward stuff but why does it say fake product that doesn't really seem right well let's see what the flow is when this when you scan an item so our search box will raise this custom event or callback called item chosen and I've wired that up here to this handle item chosen method and down here you can see that and it receives an enormous tree and is literally just the number that's printed at the bottom of a barcode so that's what the barcode scanner is providing to us here and that's all we know about what this scans so far and then we're going to try and add that to their car so I factored out the logic to that for that into this domain type called cart which is just a normal see Sharpe method see shop class and if we have a look inside there then let's see what that thing actually does okay so you can see that I've got a little bit of business logic it's kind of boring stuff and I don't want to get into it too much my logic is if you've already got one of these in your cart then we'll increase the quantity of it and if you haven't then we're going to start fetching it from the server and you can see I've got this retry loop we'll talk more about that later the relevant bit right now is this but this is where we're going to actually fetch some data from the server and as you can see it's all very fake right now so we're just waiting a little bit to pretend that we're doing some meta data access and then we returning this fake data so how can we actually get real data from the back-end server well there's one very straightforward and obvious way which is probably something that you've most of you have done probably many times in your careers if you want to get data from a server there's a good chance that you would make an HTTP request to it and you would have it return some JSON data to you and that's great that absolutely works it's very straightforward it's by far the most common way of doing this kind of data access from Blaise a web sembly up or any other kind of spa and that's great but there are some drawbacks to doing this kind of Jason over at DDP kind of approach today to access one of the drawbacks is that JSON is not a very efficient way of representing data is a very verbose way of representing data that's designed for humans and it's not even got all that much control of a precision of certain things like numbers and dates and such so is it's not necessarily the most efficient way that we could represent our data on the wire and the other thing is when you make these requests how do you know what URL to make the request to and even if you know the URL how do you know what HTTP method to use and even if you know that when the response comes back do you know what the different status codes might be and what they're supposed to mean well maybe you do but it's quite a lot to manage and there's no real formal system for tracking all this it's kind of a very much alike at an informal best efforts kind of system so you might think well hasn't anybody invented a better way of doing this isn't there perhaps a more modern way of connecting my client and my back-end server in a more performant and strongly-typed way and the answer to that is yeah absolutely there are loads of ways you can do that people soap soap it's one of them yeah we could do so people have invented many different ways of doing that over the years and one of them that has really started to get a lot of traction recently anyone guess what I'm going to say GFP C so the S peanut team did a lot of work in the three Oh time frame to make G RPC work really well on a spinet course server and just in the last week we've announced some experimental preview packages that give you support for G RPC web now G apply C web is a subset or a slight variation on G RPC that you could use from browser-based applications and I've got a browser-based application here so how about we have a go at doing some G RPC from our client application okay so how can we do that well on the server I've already got a little bit of G RPC stuff going on if we look in this proto's directory you can see inventory dot proto and that's how we define a G RPC service proto is a language independent format for describing a set of endpoints that can be called and it's strongly typed and it does some cool stuff for you for example you can automatically code generate code that can be run on the server and the client to wire all this stuff up together now at the moment I've only got one endpoint it's called autocomplete and that's the thing that is replying if I start typing into this box up here so I can just you know start adding stuff from the drop from the drop down you wouldn't have that in the real world but it's kind of helpful during development to be able to just type stuff and not use a barcode scanner all the time anyway I want to get real Product data from the server now so I'm going to add a new endpoint on the server and I'm going to define it like this it's called product details it will take a product details request and return the product details response and I haven't defined those yet so let's do that my definition will look like this the request will be the article number from the client that's all and then the response will be a product pretty straightforward stuff okay so let's build that now and once I've done that I can start filling in a server-side implementation for it and like I said this is designed to tie-in with code generation so on the server you'll see I've got this class already called inventory service which inherits from inventory base and that is automatically provided for me by the tooling which means now if added the new endpoint I can type override and you'll see that intelligence says hey why don't you consider supplying some logic for product details okay so I will what logic do I want on the server well I can do something pretty simple I can do the following I can say ok this is going to be a sync for a start I'm gonna add a bit of a delay because if I don't it's all gonna be too fast and you won't be able to see the loading states that we're going through so we'll just do that then we'll do a lookup in the database to get the product object and we can return that to the client and that's all there is to it on the server great so now I've changed my server I'm going to have to restart that and then I want to put some logic into the client to actually call it and that's pretty straightforward too because again we are able to make use of this code generation stuff so if I go into my cart data type here my domain object you'll see that in the constructor I'm receiving from the dependency injection system an instance of inventory client and that is code generated I don't have to write that and if I go down here I can now call a method on it so let's get rid of all this fake logic here and we'll see what methods are on the inventory client well you'll see that we've got autocomplete and autocomplete async but what's happened to our product details why don't we have that surely we should by now well I didn't recompile so that hasn't been regenerated yet but now every compiled you'll see now we've got autocomplete and we've got product details and we can call that from our client so the logic we're going to want on the client looks a bit like this we are going to construct a product details request with that article number we will make a request to the server and we'll get the product back out of the response so let's see what happens now and whether this stuff actually works so I'll come back over here and I'm going to scan my beans again and this time what do we get we get beans so it actually works we've got our server and our client talking GRP see yeah and so my user can now go around and do the rest of their shopping so in case you're wondering I'm working on a bit of an experimental dessert recipe right now so with my beans I want to wrap them delicately in a parcel of ready to roll icing and then to really bring out the flavors I'm gonna need a bit of this Thai fish sauce which I think will go really well but actually I'm just going to need just a bit more of that to really you know make the flavors a pop okay so we have been able to make our bigger application there speak G RPC between the client and the server and we get some benefits from that like we've got much more efficient network traffic now and we get this strongly type interoperability between the server and I claim excuse me okay so let's move off on that to the next subject that I want to talk about and this is going to be to do with testing which it's clearly a very important subject if you want to write some high quality software and one of our design goals for blazer from the very beginning has been to make sure that you can test your blazer components in a very productive and satisfying kind of way so how could you do that well traditionally there's two main approaches that you could use for testing some kind of UI component you could do unit level testing because Blazer components are just classes so you could use a normal unit testing framework to new up an instance of your component and then start calling methods on him and that's cool but it's quite low level and it doesn't give you any way of interacting with the rendered output you can't say I want to simulate clicking on a button or something because there aren't even any buttons so that doesn't you know it's very low-level way of doing testing the other more high-level way you could do it is to do some kind of browser automation using something like selenium which is something that we do a lot on the team that's building this because we need to check that the framework actually works so we've got a lot of experience of setting up this very big suite of selenium based browser automation tests and it's all very good in the sense that it's high level and you can work in terms of CSS selectors and clicking on buttons and things but it does have the drawback that these tests tend to be quite slow to execute it can take maybe a full second to execute each test and unless you're very careful about how you do it is easy to fall into the trap of making tests that are a bit flaky because they accidentally depend on some details of the order in which things are rendered all the timings of things and we've had to fight with that quite a lot so this gets us thinking can we design something that gives you a way of testing your components that has got the speed and robustness of unit tests combined with the kind of high-level expressiveness that you get with browser automation so let's have a look at an experimental version of something like that so I've got here this third project called laser mark test and I'm going to load that and if we look in there you'll see I've got this test class called car tests and it's going to be using X unit as the test framework and I'm also using this experimental thing called test hope and what that allows me to do is say I want to mount an instance of my component in this test environment it's not an actual browser but we're going to be able to simulate what happens in terms of rendering and user interactions okay so you'll remember this app component from earlier app is the root component of my application so I'm basically testing the whole thing I could test individual components at once or I can test complete groups of applications just whatever a level of the tree I choose to use as the entry point so here here I'm testing the whole thing and I'm saying that if we look for all the elements with the cart item class we won't find any because by default the car is empty that's why I'm testing here okay the next test is a bit more detailed this is going to test what happens when the user scans something so just like before we get an instance of our test component our app component and this time I'm going to do a bit of fancy mocking stuff where I'm going to intercept any requests that are made to the backend so that I can simulate different kinds of responses coming back or in this case I'm gonna simulate there is no response let's come back and then I want to simulate what happens when the user scan something now if you were wondering how this barcode scanner actually works before all it is is it just simulates a keyboard so if I scan if I scan these beams right now then in my IDE you'll see the number gets typed out by that so that's all the barcode scanner is doing and I can simulate that same action by typing into this search input a fake EAN okay then I submit the form just by pressing enter like the barcode scanner does and then I can say okay if we look for the cart items now it's not gonna be empty anymore there will be one and it will say loading on it okay that sounds believable right and then thirdly and finally we can simply can test what will happen when the server replies so I'm in the same situation as before except this time I'm going to simulate the server replying with this particular data and now I can check that inside the UI that particular product name has shown up on a certain element in the rendered output okay so let's see if this stuff actually works shall we these are standard dotnet unit tests so they will run in any dotnet test Runner for example you can run them inside the test Runner that's built into vs or on the command line whatever you like and I'm running them now it has to compile and then it runs and you can see that they've all passed and the nice thing about this is that it's very fast so the first one might take a little while to get started up because you know it's still jetting and all that but once it gets going they're really really fast so we're talking single-digit milliseconds here and it's going to be very robust because there's no out of process activity at all it's all completely synchronous in process you shouldn't get flaky behaviors okay so that's nice but can we use this to actually aid our development process in any practical way for example does this mean that we can now do test-driven development well I'm not claiming that you always should do tests of and development or necessarily think you even ever should I'm not giving you any opinion about that right now all I'm saying is if you did want to do that sort of thing then hopefully the tooling and the platform and all the libraries that we've given to you should support whatever workflow you want so let's imagine that we do want to do a bit of test-driven development right now and the feature I want to add is this one this remove item button you'll notice that if I click this button right now I'm clicking it nothing happens at all because I haven't implemented anything just yet so what behavior would we want to have well for UX that I want around removing is if the user wants to remove an item I don't want them to be able to just pick from the screen which item they're removing because if they do that they might make a mistake and remove the wrong item and then they'll get completely confused and they'll just have a disaster in the in the shop so what I want them to do instead is when they say they want to remove stuff I want them to have to scan the item that they're taking out of their trolley so you know the CCTV people can watch and see that they scan and then they put it back and they really did actually put it back yeah that's how it actually works in the shops as well so I want when I click on the remove item button for the whole UI to switch into a different mode which is about removing stuff now and then they scan and then it will switch back into the normal mode so that's quite a complicated UX flow there and since that's a bit complicated I'm going to feel better if I can define that using tests so I'm going to start by defining another test just now and it's going to be called can remove item and for this test again we'll simulate being in this situation where there's an item in the cart and then I'm going to write some assertions so I'm going to say that by default there won't be any overlay covering the screen because how I'm going to implement this is when you go into this remove mode there's going to be an overlay that fills the whole screen and displays a message but we're not in that mode by default so that should be null and if we run this test now should it pass any opinions quick no yes people say yes and they are right because there is no overlay by default I haven't implemented that so it's going to pass okay so following this test-driven counter process I'm going to add some more assertions until they start failing so this time I'm going to simulate clicking on the remove item button and now this overlay should not be null anymore it should be there I should be on the screen and there should be some text in it that says scan an item to remove and if I run the tests again now well this time we don't expect it to pass because we certainly haven't implemented any of that stuff just yet so this time when it runs the test fails and does it give us a good explanation well it says the element does not have an event handler for the event on click OK and the actual line of code that is throwing that is this one here so you can see it makes sense right you're trying to click on this item but that item doesn't even listen for clicks so it makes no sense and we're just going to fail the test so I'm gonna go over it now to this remove item button and I'm gonna put in an actual click handler so I'm gonna use at on click because the handler is gonna be a dotnet handler and not like that which could be a JavaScript one and inside there I'm gonna say let's call a method called enter remove mode all right now I'm gonna have to define that method otherwise the IDE and the compiler will start complaining at me as you can see look that doesn't exist so let's define this method and what is it going to do well it's going to do a pretty simple thing I'm just going to set a flag to true and I haven't actually defined that flag yet so let's do that okay and that's all for now let's see how far test starts passing so we'll run the test again and this time we know there is a click handler so it shouldn't fail for the same reason Atlee and this time does it pass no it still fails and this time it says there was a not null assertion failure on this line here so again it makes sense they overlay did not appear so the test should fail all right let's make the overlay appear this time so again using normal razor syntax I'm gonna say if we're in the remove mode I'm gonna display an overlay with this markup inside it now if you are wondering what overlay is is this a built in framework feature no it is not it's a very simple component that I've put in my application here called overlay and it just renders this div with this class of overlay and it puts whatever child conte inside that you want and in this case the content I want is this paragraph here so let's try running our test yet again well it's passive this time well let's see after it recompiles then this time it does pass good all right great so we're making some progress but this is not the whole Fleur that I want to test I want to test what happens now if we scan an item while we're in the remove mode so let's add a little bit of logic for that I'm going to say alright I'll simulate the barcode scanner in the same way that I did before scanning the same item that we've got in the cart and this time we should say that the cart has now become empty because we removed the thing for it and then the overlay should go away as well let's run the test yet again and see whether it passes now of course it should not because we haven't implemented the actual removal feature so it doesn't so let's implement that right now how is that going to work well I'm gonna change my handle item chosen a little bit I'll say if in remove mode is in remove mode then we'll do something and if we're not then we'll do what we were doing before and the logic I'm going to have now is cart dot remove item and we'll pass that article number through to there and we can say then the is in remove mode can go back to being false so that we're not in that mode anymore okay so as far as I'm aware we've now implemented this feature correctly so let's try that out and see if our test is any happier this time and the answer is the test passes great so we've now implemented this removed feature and we know it works because the unit test says so we don't even need to look at it in a browser because we have that much confidence right no I actually do want to see it I'm sure you want to see it as well so let's try it now let's say I've got some beans and some fish sauce then I've killed my web server so that's not so good at it let's bring that back up so look you come and now I'm going to scan my things again there and there and I decided that I don't really need those beans because Thai fish sauce is nutritious enough on its own so we'll get rid of the beans and you can see it actually works so excellent alright so that is about testing and there's a third area that I want to go onto now so another area that we haven't actually shipped anything useful for but we are planning to do so by the time this stuff ships which won't be too long is around progressive web applications or PWS so that's a pretty hot area in the front-end world at the moment has been for a year or two and these PWA api's are ways of doing desktop like things from inside a web browser and the most famous thing that you can do with the PWA api's is make your application work offline that's kind of the headline feature for PWA is in general and that would actually be really useful for us with this application because how does these devices work anyway well presumably they work by connecting to the in-store Wi-Fi so Wi-Fi is not 100% reliable what happens if a shopper comes into the shop they pick up one of these devices and they're about to start using it but at that very moment it can't connect to the Wi-Fi what's the user experience going to be like in that case well we can find out we can simulate it so I'm going to tell my browser to simulate being offline and we'll see what the user experience for our shopper is now it's now not a great user experience I think you'll agree so can we do a little bit better than that can we work offline well yes that's what our PWA api's are going to let us do and the point of me showing you this is really just because blazer is a standard it's just using standard web technologies there's nothing special or dependent on a server with it you can use all the same PW air features that you would from any other front-end application so if we want to work offline we can use something called a serviceworker sustained a javascript api and i've already got this serviceworker file in my project here so that's a big chunk of javascript and you might be thinking hang on a minute what this has meant to be a darknet thing is it why are you now showing me this massive block of JavaScript I don't want to see that well I can sympathize with that to some extent there's a good reason why the serviceworker is best to write in JavaScript and not in dotnet and that's because a serviceworker runs in a completely separate context to your application it's not running as part of your page at all so even though your page normally has a dotnet runtime inside it the serviceworker does not and theoretically you could load up a dotnet runtime inside your serviceworker if you wanted but honestly this is 40 lines of code is that too much and the other thing is you don't really even have to write these things yourself because service workers are very boilerplate T kind of things so if you go online and you do a web search for a serviceworker cookbook serviceworker boilerplate that kind of thing you'll find lots of examples of standard service workers that other people have written that do standard things like making your application work offline so that's what I've done here I've got this pretty much boilerplate serviceworker and I want to add a reference to it in my application and the way you do that is with a little bit of markup in your host page so I'm gonna say okay browser I want you to use the serviceworker api's to register this serviceworker here and now we've done that if we look in the browser console and reload you'll see it now says installing serviceworker and that code is now going to run in a separate context to my page and in fact the browser will use it whenever it's trying to make any network requests to our domain so if I hit reload you'll see every time there's a request to my domain now we get these little messages because I've put some logging inside that serviceworker just to say we can see that we're trying to make this request and because that serviceworker contains the logic to work offline to cache all this stuff and replay it if you can't reach the network let's see what happens now if we are actually offline so I'll press this offline bone again and they'll hit reload and this time we do not get the error message in fact the application just comes up and it works absolutely fine so that's pretty cool or is it well some of you may be thinking hmm so Steve you think you're very clever don't you making your application works offline but you're not clever in fact what you've done is stupid and pointless because what's gonna happen now the user is gonna start walking around the shop and they'll start scanning groceries and what's going to happen because you can't reach the server can you okay I accept that is a valid point so what's actually going to happen in reality so the users going to go around and they're going to start scanning stuff so I'll scan these beans and you can see we cannot reach the server anymore so that's sad boohoo but the good news is we're still running all of our arbitrary application logic here even though we're offline we're still running Garnett code and because there's a little bit of retry logic in there if the user later walks into an area of the shop where they do have Wi-Fi access then even without having to scan their stuff again you'll see that it recovers and it fills in the car and completes the operation correctly so we haven't achieved a miracle there we weren't able to reach the server even while we were offline but we have been able to make ourselves reasonably resilient to certain kinds of network outages which is the best I think that you could realistically hope to do so that's pretty nice ok what else can we do with this people beware api's well the other most famous thing that you can do with them is you can make your application installable so instead of accessing it through a browser the user can access it as if it was a natively installed app on their Windows Start menu their Mac dock or their iPhone or Android home screens and that's just a standard feature their browsers and operating systems provide to us so that's pretty good for us because when our customers are shoppers are using this app we don't want them to think they're using a web browser we don't want them to see an address bar because you know they'll probably just start using it for something totally unrelated so we want it to feel like a native up of its own so I'm going to do that with one of these manifest files standard PW err feature I'll give my application a name define an icon and some colors and stuff and then I'm going to rent register that in my index.html page I'm going to use one of these link tags like that and we'll see now what effect that has on the application so just before I reload I want you to watch carefully see these two icons up here well when I reload there's going to be a third one so I hit reload and you can see this little + fingers appeared now and if you click on that it prompts us do we want to install this into the operating system and I'm gonna say yep I sure do and that's now gonna pop up with its own window it doesn't have a browser address bar it's got its own color themes and everything and it is a real application it's our same application as before and the user now if they want to can find it from their Start menu like that and that will come up on its own and you know it really does work it has all the functionality that we had before so that's pretty nice so that is all I'm gonna have time to tell you about when it comes to this blazer mark thing so we've been seeing how we can use some of these things that we haven't actually shipped yet to take a blazer webassembly application and make it do cooler stuff than you would normally be able to do okay so let's now for the rest of the talk try and broaden our minds a few notches further because so far I've only really told you about a couple of things and there's actually a much bigger and more exciting world out there so do you remember back back in the day when we had this slide earlier on in the talk okay so I said that I would talk to you about the differences between these two models and and when you can use them well the first question is have these things even shipped yeah are these supported products well the answer to that is that for server-side Blaser yes that has shipped that shipped as part of dotnet Koryo which was out in september/october ish last year so this has been a shipped supported product for about four months now so yes that is absolutely a fully support thing for client-side blaze a web assembly that is currently still in preview but I know it's been improved for absolutely ages and yes we desperately want to actually ship this we finally got an actual committed release date it's not very far away from now it's in May this year so just a few more months to go until that is shipped and supported as well okay so the next question to ask is which of these two models is actually the right one for your situation and before I answer that I just want to really emphasize this key point that you've got to get into your mind which is it's not really an either-or situation it's the same programming model that's going to work in both environments so if you buy into the idea of building a blazer UI then you can choose to run it on the server or you can choose to run it on the client you can start on the server and move to the client you can start on the client and move to the server you can even in some crazy advanced cases create an application that does both at once if you want to so that's the flexibility that you're getting by buying into this pattern but still the question is which one still is the one that you would actually want to use well it depends on your situation obviously so when it comes to server-side Blaser that's going to be the best choice for you if your users have got a reliable low latency connection to your server and the reason why it's going to be the best in that case is because it's much much simpler you don't have to actually send the dotnet runtime into the browser you don't have to send your own code into the browser everything's running on the server in a much more predictable and controlled environment and the UI updates are just being streamed over the wire down into the browser so that's a very straightforward solution for you and it means that you can work with very low powered devices because they're not really doing any significant work so that's nice on the other hand the best situation for doing client-side blair's a web assembly is going to be in cases where you want to not rely on access to the server so if you want to actually work offline then you absolutely need to be running on webassembly Leykis there's no server in that case or if you need to have incredibly fast fine-grained UI updates then blaze a web assembly is going to be the best choice for you there as well because you don't have to wait for any traffic network traffic in order to update the UI and the other cool thing about blazer on webassembly is to do with hosting so when you publish your webassembly app there is no specific server requirement it's just a set of static files as far as your server is concerned so you don't need dotnet on the server you don't need anything in particular on the server you just need to be able to serve files so you could host it on something like a CDN or a blob store or anything else like that and to prove that to you let me show you in my browser now if I load this bookmark blazer Mart live you'll see that actually opens my site just like before and it works just like before but have a look at the URL there you'll see that this has actually been hosted on github pages which as you can understand is a very very cheap way of hosting your application it's free its globally distributed and ablaze the webassembly application can be served from that just like it can be served from anywhere else so that's one of the cool things okay now so far I've only talked to you about ways of running your application inside a browser but Blaser is a more flexible programming model than just that you can run it in other places too what if you didn't want to make something that people load in their browser you don't want to be subject to normal browser sandbox limitations but you actually want to make a native application running regular native code and have that pop up on a user's desktop for example you won't want to build something like an electron application with Blaser well we've been doing quite a bit of experimentation with that recently and we've got some samples for you to try out if you're interested so we've got a sample of doing blazer with electron we've got a sample of something called web window which is like a very lightweight alternative to electron it's very experimental but it involves it doesn't involve bundling a browser it doesn't involve bundling node so it's a much more lightweight way of bringing up a desktop application that contains a blazer UI if you want so see those samples if you want and then in this bottom right corner but there's something even more future and elaborate and we haven't really even done it yet but I want to talk about anyway and so what if we don't want to use web-based rendering technology at all we don't want to use HTML and CSS why if we wanted to make a native mobile application for iOS or Android or or even a native desktop application and instead of rendering through web technologies we want to render native OS components well we've got a sample of that as well and just to really emphasize neither the hybrid northern native options are committed products yet these are just experiments but we do really want to get your feedback about whether these things should be made into real products and I want to show you an example of something called mobile blazer bindings which is a collaboration between the xamarin team who mostly did the work and the blazer team who just get to take credit and I'll show you how we music to build a native iOS application using blazer as a programming model so let's switch back into the IDE for the last time now and I'm gonna load something called blazer mobile app which is not the most creative name and inside there you'll see I've got three projects I've got blaze a mobile app which is a blazer application so it contains a bunch of razor files and c-sharp files and it's the same programming model that you know and love by now and we've also got Android and iOS projects there is a really any significant amount of coding those two at the bottom they're just little shell wrapper applications that know how to start up on each of those two operating systems and I'm gonna use the iOS one right now so I'll show you the code in a minute but first I want to show you the app actually running so all being well I'm gonna be able to make my phone screen appear in front of your just now let's see if this works okay yeah very good okay so this is a iPhone a normal iPhone you know them does all the normal I for any things and I've built this application here and deployed it onto my phone so if I start that up when that comes up that is not running inside a browser there's no wk webview or any other kind of browser rendering technology this is native iOS elements and we've got all the usual kind of demo things in here so I've got this button I can tap on it and it says how many times I've clicked it I can move on to the to-do list we'll do that in a minute and we've got calculator so that's all just being rendered using Blaser components and it works cool what about this to-do list well it's just you know the usual industry standard to-do list that we always have to show let's add some stuff to the list so we'll have stuff okay and I'm gonna tap on this Add button what will it do oh what a shocker what a disappointment we haven't yet implemented the add item feature which means we're going to have to implement it just now as a demo okay so let's have a look at some of the code in this application well let's start with this counter right here now if you are familiar with the brave blaze a programming model this should look pretty familiar to you this is pretty much the same as the web-based counter with one kind of important difference so inside the code block here we've got exactly the same code as normal just normal c-sharp code that's gotta count in an increment count button and above that we've got markup but it's not HTML this time and in fact I cannot use HTML even if I wanted to because there is no browser here the only thing I can use are these native iOS elements and the ones I'm using are this stack layout this label and a button so we've got a label that says how many times you've clicked and a button that when you click it it cause increment count and that behaves in exactly the way that you think it should okay and what about the to-do list well there's a bit more going on with this one let's just go through it step by step okay so to get started with we've got this to-do item class here with the usual is done and text properties on it we've got a list of to-do items and we've got a new text string where the user can enter some new text and up at the top here we've got this entry which is the thing that the xamarin team uses to mean text box and we've bound that to this new text field there and then I've got a button that says when you click it will call add item and inside on out add item we're rendering this little popup message so let's fill in an actual implementation there so I'm going to say to-do items dot add new to-do item and we'll set the text on there to be the new text okay and then I want the text box to get cleared out so I'm going to say a new text goes back to being its default value of not okay I also need to actually display these items and because this is not zamel I don't have to do any complicated stuff with bindings or whatever if I want to iterate over things and make a list well I just go for each with normalcy shop syntax for each item in to-do items I'm going to render a to-do list item and the thing that I'm going to pass to that is the item okay very good so that's pretty much all I have to do but I'm just going to do one more thing because I like to I'm going to also display the number of items that have not been completed yet so I'm gonna say we'll get your to-do items and we'll count all the ones in it for which the is done property is still false okay now let's try compiling that now and we'll see if that actually builds and hopefully it will it does okay now I've also got that version of it on my phone as well so I'm going to start that up and we'll see what happens now so if I go into this to-do list now and I start entering something so I'm think this time when I tap on the Add button you'll see it does actually show up in my list and I can do more things let's herb laser is let's just do this third day you get to the lobby okay cool that makes total sense to me don't about you and then I can start toggling these buttons and it all works you see the the number of dates as I do that and we have all the usual scrolling and stuff so we've been able to create a native feeling iOS application using the blazer programming model and without having to use any sort of web rendering technology okay so that is it that's all we have time for today so I hope some of that has been interesting and useful for you if you want to learn more about this stuff if you want to learn more about blazer then go to blazer on net if you want the code and the slides from this talk then go to the URL that's up there and you can download that and see that for yourself so I hope that's been fun and I hope you have a really good rest of the conference thank you for coming [Applause]
Info
Channel: NDC Conferences
Views: 91,309
Rating: undefined out of 5
Keywords: Steve Sanderson, Blazor, UI, Framework, .NET Core 3, C#, Razor, (SPA), WebAssembly, NDC, London, 2020
Id: Khn7sDUSEJM
Channel Id: undefined
Length: 61min 13sec (3673 seconds)
Published: Thu Feb 13 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.