Video details

Building a real-time serverless app in Blazor using AWS | Martin Beeby

Serverless
09.11.2020
English

Martin Beeby

In this session, we will build an interactive dashboard using Blazor that reacts in real-time to events that happen in the real world. We will connect the Blazor application through to a serverless backend built in .Net. Rather than requiring a cluster of servers to maintain our WebSocket communications, we will use a managed service called Amazon API Gateway and take advantage of it’s WebSockets support. This service introduces a whole new way of thinking about, and architecting, applications that require duplex communication.
By the end of the session, you will have the knowledge to build highly scalable and resilient real-time applications without having to manage or scale servers.

Transcript

OK, hello, everybody. It is time, it's for 440 here in the U.K., it's 540 in Oslo, certainly can't be in Oslo today. It's a real shame. I always look forward to and see Oslo every year. And I've been going for many years. My name is Mike Beebe. I'm a principal developer advocate, eight of us. And today I'm going to be talking to you about building a real time service application in Blazer, using a US. If you want to contact me, I'm at the Beeb's on Twitter. You can see me all the way down that screen there at the beads. And if you've got any questions or anything which come to mind after this or if you're watching the video replay of this, then please just tweet me at that address and give me any questions you have and I'll get and I'll get back to you. Also, if you have any requirements for a free trial of us or you want some credit, TriWest, I can give you a fifty dollar trial for us. Just tweet me or Dmae at the beeves and I will set you up with that. So without any further ado, let's talk a little bit about building real time surveillance applications. Employers are using eight of us. So we're going to be showing you what I'm talking about in terms of what a real application, real time application is, because there's lots of different definitions for it. So I just want a level set I'm talking about. I'm going to show you how you could build those sorts of things with Signaler, and then I'm going to be showing you how you could build those sorts of things using serverless technology and in particular will be using the LAMDA service from us using CE up. And then finally, I'm going to show you how you combine more to build a serverless and laser application. And one of the advantages of doing that and the whole reason for doing that is, is basically the costs involved. So to build the signature application and to have it working at certain scale is going to cost me probably hundreds of pounds a month, hundreds of euros a month to run, whereas the service application will only cost me what it cost me, very, very little. But more importantly, I actually only pay for the times that's being invoked and being used. So if someone actually makes a request in my on my application and I'm actually paying per request rather than paying paying for the infrastructure which is just sitting there. So that's the reason I'm moving this to a service rather than just being a standard real time application is is to try and save money fundamentally. So when I talk about real time applications, there's lots of different types of applications that are real time. And the common example would be something like a chat application. So it's like WhatsApp when you're texting and you're sending a text message to somebody, that message is obviously being delivered in real time so that they're able to converse and be able to chat. But also things that aren't so obvious are also being done in real time as well. So things like notifications, things like little read notifications, like the double take in WhatsApp, which shows you that someone's read your message. That's a real time notification which is happening. Some event is happening in the real world. And you're being alerted to that event happening and taking place with the Double-take. And also when someone's typing a message in WhatsApp, there's a really irritating sort of signal sent to the other user to say that that person's typing so they can be expecting that sort of stuff. So you'll see in lots of different styles of application from, you know, a news website, when a breaking news story hits, we're maybe sending that we're pushing that data out to the users in that browser. So it pops up as a little pop up. Now, to do that, we need some way of pushing data from the server to the actual client user. And that's what a real time application is really. It's an application that not only can you can browse when you can look at information, but it can receive events coming in from the real world. So if a breaking news story breaks, then that can alert your application and then the UI can respond by popping up some information. That is a breaking news story, multiplayer games. So if you've ever used a massive multiplayer online games and other characters, their health, their position in the game, all of that stuff is being relayed to you in real time, probably using some of the or similar real time technology like the ones we're going to be showing you today and document collaboration. I use things like Quitte or Google Docs. When you're editing a document and someone else is participating with that editing, they're doing that in real time and they're using real time web technologies. And we'll also take a look at a couple of those. So here's an example on on looking dotcom. I haven't actually had to book a hotel in an awful long time. So this is but, you know, if you go to. Booking dotcom, and you were looking at a particular hotel, you'll know at a certain point in your journey they pop up a little message like this. And so it's just booked in London, 52 proxy's like this Hilton in London. And there's a number of ways they could implement this, right? They could implement this on a timer. So, you know, after 15 seconds of browsing a property, they could just put up this this this guy. But what I'd like to think is that they're doing this in real time. The someone actually physically really booked this particular hotel and that they're showing you that in the in the UI. Now, I don't know if that's exactly what they are doing in this scenario, but it's an example of a real time interaction and trying to drive the user to go and book this hotel because they're getting this impression that it's being booked all the time. Maybe they're going to not able to get a room and so forth, but something's happened somewhere else. And the server sent an event down to the browser to say that someone's just booked that particular property and then the is responded accordingly, which is a document collaboration system called Quit. I think it's by Salesforce. And it's a bit like Google Docs, I guess. And one of the cool things I really like about this application is that you can view who's viewing the document and this is really useful if you send out a if you send out a document, we have this thing in us where we send up a document and we read the document during the meeting. It's a it's a peculiarity of the Amazon works. So we'll send a document out at the start of the meeting and then we read it for like ten minutes and then we get on with the rest of the meeting. Everyone's on the same page and everyone's definitely read the document before we start discussing it. Now, one of the cool things about the viewing thing is that you can actually see that other people are connected to the document and are viewing it. They're reading it. And so, you know that they have received the link for the document. You can see that there are six people in the meeting. You can see that six people are viewing the document. They've all managed to get access to the document, that sort of thing. And also it has things like there's a chat functionality and quit and even has that really ignore it. Knowing you are about typing where you know someone as they're typing it shows you, oh, Ron Swanson is typing and you can sort of is indicated in real time. They're doing that. Now, if you think about what's happening when that user is pressing keys on their keyboard in that particular message box, sending a signal to a server somewhere, then that server is then relaying it to everybody, which is viewing that document. But someone particular is is is typing. So these are this is an example of a real time event, something happening in the real world, being relayed to multiple people in real time to give a better experience for that user. But this is a particularly annoying UI because what I always find is someone starts typing and you go, oh, what are you typing? So you're waiting, you're waiting. And then they delete the message and then you Afghani's. Right. So there's certain anti patent's perhaps to real time applications. But it's it's a useful piece of user interface which is developing. So the vast majority of applications today are going to be using WebSocket to achieve this real time application, now that that's whether they're a browser based application or whether they are a mobile phone application or even an Iot application. They'll probably be using something like WebSocket or in fact, they'll be using WebSocket to to communicate. Now, WebSocket is a it's a protocol which allows us to send messages not only to a server, but receive them back from a server. And that's really something which HTP isn't capable of. You can send a message to to a server and make a request and it gives you a response. But the server then can't at a later stage send you something else. You know, it's a one time thing and the request always comes from the user making a request of the page or the web server. The server can't ever make a request back to the user. Well, WebSocket solves that problem by basically creating or instantiating a pipe between the server and the application by which communications can travel back and forth. And the good thing about WebSocket is once you've got the pipe set up, there's no serious overheads in terms of the data which is being transmitted. So with HTP request, every time you make a request, you have to send over the cookies, you have to send over the headers. You have to lots of stuff other than just the request which goes through. But where the WebSocket connection, you can just send literally the data once it's started and negotiated and set up, then data can freely transfer between the app and the server or more importantly, from the server directly to the app. Now WebSocket negotiation happens, something like this. You make a HTTP request to the server and it's a specifically request crafted HTTP request, negotiation, handshake. And it says basically to the server, do you support WebSocket? And the web server replies, look, it's 2020. Of course I do. That wasn't always the case years ago. There's absolutely servers and application frameworks which did not support WebSocket. But in almost all scenarios nowadays you'll find that most, mostly the clients and mostly the servers will basically support WebSocket. And because they both both sides of this equation support WebSocket, and both sides have to be able to support WebSocket to enable it, they will be able to create a new pipe which they can communicate between each other. So when I got into real time applications or building real applications, it was sort of around 2008, 2009 time and I was using a framework or I got into a framework called Signal. Signaler is an incredible framework for building these sorts of real time applications. And it means that you don't really need very much understanding of how WebSocket work. You can program in C Sharp and and it's got a really nice sort of developer abstraction over the top of it and. You know, it makes it very simple to write small applications. It's an open source framework. You can still use it today. You can use that for the full framework or you can use it in Donette core as well. It's it is open source, as I say, and he supports a number of different transports. So I've thought about WebSocket. There are other transports that I'm not going to go into, but there are other ways of doing real time communication and signals really nice in that it wraps them all up for you and basically chooses whichever is the best option at the time, depending on what the service supports, what the application supports and various other things. It's not it's not about Cingular, but it's just an important thing to sort of explain what I'm trying to build here, because when I built my signature application and I moved to us, which is about a year and a half ago, I decided to see how I could deploy a similar application on AWB. Now, the simplest service, AWB, I'd say, to publish a dot net application is a service called Amazon Elastic Beanstalk. And what that does is if you're in visual studio, let's say you can build a dot net application, dot net for framework or dot net call and you build it. And if you have the SDK installed, you can right. Click the project and you can say deploy to elastic beanstalk. And what it will do is you wrap up your code, build your code, put it into a zip file effectively and in the background it posts that to us and then us takes that code and it puts it on some infrastructure. Now, the infrastructure that you set up, you can say, I want one server, I want 10 servers, I want it to auto scale between one and 10 servers. I want to load balancer in front of it. You make all those decisions when you're doing the deployment and then it will basically put the Web application on however many servers that you want. So I put my SIGNALER application, I stick it on, I build it using Elastic Bienstock. Because it's easier to use the visual studio way of doing it, but you could easily, easily do it from a command line as well. But I say, OK, publish it to Bienstock. And what it does is it creates a low balance for me and it creates two instances. So I've got two instances sorry, two Web service, as we call those instances, two instances, each running my application and a load balancer which load balances between the two. Now, the only thing that I had to change really to get this working was to say, well, the load balancer that needs to be sticky sessions because the way signal works once the Web connection is set up, a WebSocket connection set up, you want the person going back to the same Web server. So I set up sticky sessions on the load balancer and pretty much my application works. So just to show you what that application looks like, if we go if you have a mobile phone and you have a camera. Or if you just want to punch in the URL signal, dot the beach dot net. And I'm going to share it with my camera, this QR code, and it'll take me to the URL and I should then receive like a little sting, which says, please wait. So it's like a little gray screen, so once a couple of people of have gone to that site, then I will be able to do is I should be able to go and click through to the next thing. And what will happen is my phone will have been updated with a question, says what? Drink coffee or beer. And I see a few of you have already started to vote and five of you saying coffee, siccing beer, I'm going to vote for coffee. I don't drink six and six. So today we've got like six, seven actually coffees, coffees, taking the lead list. There's there's people voting for coffee and beer using the application. And you'll see that as you press the button on the application. It sends a signal that's received by the application updates the counter on one of the sites right now if I go over to Tabatabai Spaces. Interesting. I don't know quite what went wrong, but you can vote versus Tatebayashi spaces and we can see before it crashed out, I don't know why it's doing that, but. Never mind, we have roughly journalese going to say that Tab's tabs are winning for some reason, I'm going to take it off that screen. For some reason, it's not quite working how I expect it to. Luckily, the signal is not actually what I was going to show today. So that's that's good. But. Roughly, what's happening there? The idea is we've got a load balancer, we've got two instances and it's balancing between the two. Applications working as you connect to it, you're connecting to one of those two instances and all should be kind of well with that, but there is a slight problem if. Because we have two instances and we have messages going back and forth and WebSocket, when I vote, the voting doesn't always happen on the message, doesn't always get sent to both machines. You see, when I say I'm voting or incrementing number to say I want to vote for coffee, that that message only gets sent to the server that I'm connected to. It doesn't get distributed to the other servers. And so this is a common problem in real time applications. If you've got a ballot, you've got a number of servers which are in an application, then they actually need to talk to each other as well as to be able to pass the messages back and forth so that you've got the correct messages going to. So the applications function correctly as a sort of unit rather than as individual applications separate. Now, the way that we solve this in something like SIGNALER and in many sort of common scenarios is we use a thing called a backplane. And a backplane is basically some kind of mechanism which stands behind the application, which we can communicate so the servers can cross, communicate and pass the messages back and forth so that everyone's got the correct messages in the real time applications. And now. To do that, all of us. OK, now I would have to go and set up a checkpoint and signal are the preferred back pain for signal. Isn't it cool, reddish? We have a service called Amazon, the LASTA Cash for Radice, which is basically a managed redish service so I can stand up a managed radio service and it's set up as my backplane. Once I've basically created that that thing, I go into my Natcore application and all I have to do is actually add this one line of code or a couple of lines of code which says On my signal, our installation ad stack exchange readies and then I pass the connection string to my Redish cluster. And then I set up a channel prefix, which basically means the communications for this particular. My application is going to communicate on this particular channel called My Up and then basically. That's really all you have to do to set up the backplane and Signaler Singler takes a lot of the complication out of something like this. But there is a challenge with this now. OK, I wanted it to build a simple, real time application. And all of a sudden I've got a load balancer, I've got two machines, I've maybe got 10 machines, and then I've got to have a backpack, a backplane, which is a cluster of machines running redish. And all of a sudden this is starting to get quite expensive. So to do a demo like I did before or I had one or two machines, it's not very expensive to run something like that. But when you were actually scaling this, if you wanted to build Facebook Messenger on this infrastructure or some kind of chat application where you're expecting hundreds or thousands of people to be communicating at one time, or you're building a real time news application which is doing updates in the browser of real time events happening, then you're going to have to scale this infrastructure pretty, pretty hard and it's going to be expensive and it's going to be complicated. So. I was kind of wondering, well, is there an easier way and a few years ago, eight of us released a thing called the API Gateway, API Gateway WebSocket. And this is what I'm going to be integrating today into a Blazer application. So API Gateway and WebSocket is basically a API gateway is almost like a thing which just stands up in the cloud and you can send messages to it and it will route those messages to other systems. So you can think of it as like a gateway for your API. I don't know why I said that you can think of it is like a slot that you put in front of your application to provide an API or unified endpoint to your application. And your application doesn't have to be one single application. It could be multiple applications, but your unifying them through the API gateway. So that's what API was commonly used for. But then they added the support for WebSocket. And what that means is that you can basically not only can you manage to use it like for an API, you can also deal with WebSocket communication. And what they're promising is basically will manage all of the WebSocket communication stuff for you and you just implement your application as you would normally. And we will maintain all the connections for the clients and will set up a system where you can post to all of your connected clients. But it's much more straightforward than having to deal with WebSocket natively. So let's explain a little bit more about what this means. So we have applications or things like mobile applications, applications, dashboards, Iot devices, web browsers which connect to our API gateway, and so they connect to a WebSocket end point and a WebSocket URL. And then in the back end, we have our infrastructure. Now I'm going to be building using Cervalis infrastructure. So I'm going to be using LAMDA functions in the background. But these could be containers, they could be an existing API, whatever really API we can forward onto any kind of other system. But I'm going to set up a WebSocket system and then I'm going to forward it to some lambda functions. So what happens is the mobile application is just going to use this standard WebSocket client that it has in its SDK and it's going to connect to WebSocket End Point that the Amazon API gateway is going to provide. So that's going to be like colon slash slash. So instead of HDB or HDB, it's going to say, which is basically a websocket secure, a secure websocket, you'll sometimes see a colon that's just a websocket, but a websocket chalons secure websocket. Then it's going to have a unique ID. Executer API, then the region that this is running in. So if I was using it in an E w one, it would say e ust one that Amazon.com forward slash and then the name of the stage that you're using and you can create in the API at different stages, whether they be product or test or something like that. I often just use the stage name product because I like pushing everything to production. And what happens is these these devices connect the API gateway and they start up a WebSocket connection between the two. But API Gateway, when it receives a message over the WebSocket, it just invokes whatever's on the back end, like a restful communication doesn't do over WebSocket. It just invokes it, invokes it, and it passes over to the invocation, a connection ID. And the idea is that because you've been invoked and you've got a connection ID, if you want to speak back to that connection, you have this idea that you could call a later date. So you have this duplex communication up. But it's important to remember that the lambda functions themselves have no idea that they are involved in a real time application. They are just dumb lambda functions and they're receiving an invocation with a connection. I do. And if they want to, they can respond to that connection, I'd. Well, I actually do when when someone connects to this system, they pass over the connection and I put it into a database and in this instance we're using Dinamo DB and basically any one which connects to my WebSocket, I put their ID into a database and then we have a way of taking those IDs out of the database and calling them and basically sending a message to everyone. So we're able to send messages to everyone which is currently connected to our system. If I loop over the database, all the connection IDs and I use this particular URL with this connection I'd crafted on it, I can post messages to the individuals and I'm actually not posting messages to the individual people. What I'm doing is I'm posting a message back to the Amazon API gateway and then that's then forwarding it onto the correct connection. So from an end point user point of view, they have got this real time communication happening. But the reality is it's all the magic is all happening in the API gateway. It's the one which is instead is maintaining the connections. It's the one which is understanding or creating connection IDs and matching them back up and packaging messages, messages back and forth. So we have this thing called the WebSocket URL, and as a message is being sent to the API, Gateway invokes the invokes the LAMDA function and we store some of that in Dinamo DB. Let's say now we want to do the opposite way, we want the server to be able to message the client. Now, I mentioned before I can have a lamda function, which basically goes into all of my Dinamo DB database. It gets a list of all of the connection IDs and then it posts something to each of those connections, the way it posts them. Is that just use a connection, you URL. It's called a connection URL. It's got a random number, the region number. And then here at the end, a really important bit, which is the connection ID. And if you do a post to that connection ID, then you can send a message to it and it will get routed by API Gateway back to the person which which invoked it. Right. Now, the connection, Earl has a couple of methods on it we can pose to it, which is send a message to that particular user, we could do a get on it, which basically gives us the the status of that current user or we can delete it, which removes that user from our system. Or basically to disconnect the socket, you are there, WebSocket. So if we want to create one of these APIs. We go into eight of us console and we create a a WebSocket API. We give the API a name. My fancy NBC. API, we give it a think of a selection expression. This is basically what the API gateway is going to use to route the messages coming in, the different lambda functions. And then once I have that created. Once I have the API I created. You'll see that there's a couple of routes already set up. So what we can do is we can say we're going to connect this particular group to a lamda function and we're going to just I've got some LAMDA functions already set up. One called on Connect. I'm going to set up the disconnect one as well as lambda function, which happens or is called what anyone called disconnect to the service. And we've got to create a new route called Send a Message. And we're going to put that into the Alamdar function, a message. I've got three functions, LAMDA functions. And one API gateway. Deploy the API. You stage a name, you can have as many stage as you like, I'll call one cattle prod. It's my production API. Deploy that. And then you'll see we have this WebSocket Yoro, and we have a connection, you are all so you are all for that particular connection. So the WebSocket Yoro is what we would use instead of our application to instantiate or create a WebSocket communication to our application. And the connection URL is if we have a connection ID or a number of text, think we can we can basically post those connection IDs and send messages to the different people connected to our service. So my application, what it does is it crafts this particular this sort payload, and this is what the message that passes through the the WebSocket. And when I pass this message, you'll see that it's got this this this one property called message send message. Now, message is what it's actually going to be routed on. So it's like the Ruki. So if I pass this, it's going to be my API gateway is going to receive it as a WebSocket request and it's going to say, OK, send message, let me go and route that to the send message lamda function. You don't have to be allowed to function. I could have it to an API endpoint, which is backed by an IRS Web server. I could know it doesn't have to be a lambda function, but I'm going to post it to allow this lambda function. And that's the connections that I've made. And the data that I'm going to pass over is just saying hello in D.C.. Now, this this doesn't have to just be a such a simple package. It could be it could have multiple things and it doesn't even actually need to be adjacent. But that helps with the scenario we're doing. So I'm going to just say I want a message. We send message. And if I posted this to that particular WebSocket URL, then I would have posted a message and it would get routed to my lambda function called sen function. This is the way that my architecture looks in this scenario. We have the Amazon API gateway, the client application now client application can be really done. It can just be htp html sorry page. That's a very straightforward, inexpensive, static website and that's just going to create a websocket and then that will connect it up to API Gateway. And then as I send messages to it, it's going to route those messages to the correct lambda functions. Now when I instantiate a connection, the first thing that's going to happen when I instantiate a WebSocket communication by default, the thing that gets passed is on connect. So what happens is it will go to the on Connect Lambda function. Now my own connect lambda function. What it does is it takes the connection ID which is passed to it and it stores it in Dinamo DB. I also have a lamda on disconnect function, and so whenever someone disconnect from the WebSocket, it will automatically send a message to that which basically says, hey, this is an idea which is no longer connected to the service. And what that function does is it goes into the database and it removes that connection. I think the point being, my Dinamo DB should have a list of connection IDs at any given point of everyone connected to my application. Now I'm using Dinamo DB as a storage, but this could be any kind of cache, really. And what send messages doing that as well is once someone's someone makes a message and craft it in that particular way, so that uses the send message functionality, it will go to the Dinamo DB, it will download all of the current connected clients. It will send the message to each of those connected clients. And so everyone receives the message. So this is I won't go too much into the code because I have it on GitHub and I can share it later. It'll be easier probably to look at there. But basically, this is the send my message function now to send a message function, what it's doing, and it's got some logging in and so forth here. But we're taking this property, the data property, which is the message we're putting into a stream and then we're asking for this is a way that we don't get all of the items inside of Dinamo DB Darmody, by the way, is there no SQL database, very performant, quite well suited for this kind of task. And it basically does a scan and says, give me back all of the all of the connection IDs. And once I've got those connection IDs I can do is I can loop through them. So for each item in those connection IDs and for each of those, what I'm ultimately doing is I'm posting the message to the connection. So I use this little helper function to actually create the URL for me and create the the connection for me. But ultimately I'm basically looping through if it's 500 people connected to my service or look for those 500 people and I'll send them all a message via a post effectively. So let's just show you what that ends up looking like. So if I go to a website called Chat Dot, the Beeb's dot net. You see, it's pre-treated with a euro or it's already got a URL in there and I can connect to that euro. Should be correct, yeah, and if you go to chapel to be used that as well, you can join in with this one to let me go and set up another browser. And it's up, and if I type in Hadlow that. Oh, yeah, I received the messages hello, which I sent and someone else's sent a message as well. And then on the other side you can see so I can say window. One send message here, window one, and I can say window two here. And someone said, hey there as well, so people are connecting to this application and it's basically a very, very straightforward and simple application is using that connectivity in the background now, I think. Let me how if you go to my GitHub. You have the beads. Sorry, I can't remember the name of the repository. There's one. So the actual code, which is running on the screen there is just a simple HTML page, super straightforward, it's built in and this in view I can't remember. If I look at the JavaScript. You'll see that I have a. A connect function, a disconnect function, the same message function, and it's just basically crafting these send messages, just crafting things that send message. In a passings and recrossed. Unconnected is just setting up a WebSocket connection. And I'm using that to kind of update the scenario in the screen, so that's the code to kind of enable that, but it's all in JavaScript and I'm talking about something else today. We'll talk about it later. So how would you go in head and kind of do something similar? But let's do it in plaisir now. In plaisir. We've got two different ways of running a running blazer. We've got a thing called Blaze, a web assembly. And we got a thing called blazer server. Now, I'm not going to be talking at all about Blazier Server today. I'm going to be talking about Blazer Web assembly. And the reason is because Blazer Web assembly is better suited for what I'm trying to do here. What I want is to create basically a view James style Web application or a react style Web application. But I don't want to use JavaScript. I want to use as much as possible. So I'm going to be using laser web is simply what allows me to do is create like uys using web technologies. But all of the logic isn't written in JavaScript. It's all written in dot net and behind the scenes. What it's doing is it's using Web assembly to run your application. And what assembly is a is a new feature of browsers. And it's it's kind of this weird way of being able to execute things or run things which previously wasn't able to do. And some clever people have decided that we could actually run other programming languages inside browsers now. And PLAISIR is basically a Web assembly is that it's a really clever little framework for building Web applications, but using C sharp. Now, this doesn't mean we're going to be using any kinds of plug ins. This is not Silverlight, it's just using native web technologies. And it will only obviously work in browsers that support Web assembly. But nowadays that is almost every every major browser. But it wouldn't obviously work in. If you're still supporting I9, this won't work. But the Blazers serve as a similar thing and you can take the same application. But this would work in something which is a much older browser, but it requires the server to be doing a lot of the processing and actually uses WebSocket in the background to achieve that. It plays a server hosting model, but we're not going to talk about like a server. It's interesting, but I've already I've already pretty much run out of time for that. So what you can talk about is a Web assembly. And what I was kind of looking at is, well, how do I pull that first application I built into something like Plaisir? Now, I haven't quite got the style the same. And it's just purely technically how I would go about and do it. And this is a road I started down about nine months ago and I've gradually kind of like the application as Blaze's matured and added new features to it and and got it to a point where I think it kind of does everything that it does everything that this the application does, it just doesn't quite look as pre. That's another job that I need to do. And so did start with plaisir. We just go to the place, a site. There's a little getting started application documentation. If you click on that, it's going to tell you to install dot net three point whatever it is nowadays. And then once you've done that with the command line, you can say dot net, new blazer wasm. That's plaisir web assembly. And then we give it an output like name for our project, which is always a front end in this instance, and that I cwd into that folder and then you can just say dot net run and it will build your application. And it's got a very basic application where you can click a ticker and it will update a number and increment. No, the cool thing is everything in that browser, all of the logic isn't done in JavaScript or in. So my application, I've basically tried to use that base application as much as possible, and I've made a few modifications to it. So one, I've added a a question, Jason, with sample data. So my questions at the moment are just hard coded into the application. Obviously, I won't do that in the real application. And I've got like a question ID zero and a question I.D. one, and it's got Tapsell spaces and coffee and beer. And so this is roughly the data that my real application I actually store in a database, but I'm going to be just storing it locally here and. Um, I have a couple of pages that I've added, I've got the index page, a page called Questions and a page called Vote. Again, it's similar to my application, I have like a voting screen, so if you went and voted a moment ago using the application, that was a voting screen that you said, please wait. And then you choose one of the two options and so forth. That's the voting screen. And the question screen is the screen that I present to you, which shows you the QR code and then shows you as you move the slides or you move the questions. And so those are the two kind of like screens in our system effectively. So I've added those as Rasor pages. Now, the first thing I do in the questions raise of you is we have this event which says protected override async task on initialised async. So there's this kind of workflow in a lifecycle, I suppose, in a blazer application. And the first thing when someone navigates to the questions page, it's going to invoke this on initialised async task. Now, I have just very lazily placed the first thing that does is it loads whatever was in my questions got Jason locally. That's a local local file. But it could obviously just pull this from, you know, a database or another API and it loads it into an object called Questions. Now, questions is basically a list of my this type of questions. So I end up with a list of questions. Now, if you've ever you single page applications before, you'll know that the whole point of them really is that you can create a state so I can have an application state and my UI automatically updates and reflects that. So I don't actually have to bind, manually bind my objects to my state. So now I've got a list of questions. I can basically create a UI which loops through those questions. In my view, is the view which which displays those questions, so I've got a if the questions are now so there's nothing in the questions, then show a screen which says loading else at the table and the tables got title to one answer to answer, one count and to to count. Now, in the real application, I use some fancy grap more fancy graphics to display the images to have that little graph in the middle. For the purposes of this I'm just going to just print it out to a table so you can see what's going on. And so at the stop there, we've got the sort of the the questions, the thing that I'm injecting that you'll see at the top is the HTP client list, how we do dependency injection in plaisir. We can also import new get packages if we want. You get packages in the top that we could if we wanted to use new and soft, Jason or something like that, then you can just import that like you would see shapefile. It's got a slightly different syntax, but it's ultimately what you're doing. Or like third party libraries, you can import them and then you can use them inside of your application. So I'm saying, OK, show me the loading screen if the question is now, but then show me the table. And that table has some logic in it, which says for each question in question, so it's looping through all of the questions that I have in this instance, I've got to and it's saying if I equals current account on line twenty seven, then show that question. So I've got a really like a really ugly way of basically saying look through all the questions and only show the one that it's currently set. But I've just got a variable called Current Account, which is basically an integer, which is going to be it's going to be zero one in this application and it is zero, which are the first question. If it's one, it will show the second question. And if I had ten questions, obviously would increment and only show that particular question. And then at the bottom, I have these buttons and it says on Click that button that execute a special handler called previous question or one called next question. So you'll see these are HTML buttons. And I've got these two values in them. But just buttons, and this is sort of like a decoration that you can put on Blazer objects to, say, invoke some C shop and then the actual handlers, well, they just look like sharp handlers. We've got a next question and a previous question. Now, I said before, the logic is really driven by what the current account value is, because as I change the current account value, that view is going to alter. You can imagine every time that you alter the application state, it will update the UI automatically. So all I actually have to do is alter the current account variable to be the zero one. And it was effectively switching the questions. The view will look like the questions got switched. So I just have a next question and a previous question has got some logic basically to say when I click next question and increment the current count by one, but don't go any higher than that. I have questions and previous questions do. Exactly. Take one off the current count, but don't go lower than the one. So I now can help with these two buttons, I can navigate all the questions in my application at the moment. That's just to. So that's kind of the the view that I have. Now, what this looks like is difficult questions, now I've got my question, Tab's or spaces and answer the next of previous, it just basically cycles through. What's cool about this is I'm not updating the UI at all. I'm just updating my application state and the UI reflecting those changes. So the voting screen is really similar. But all I want to do is basically add some buttons so they can vote, right? So I've got a very similar sort of set up, but you'll see online line 37 here. I've got a button which says vote and to one or vote answer to. And it shows the question, information about the question, you'll see that when I look through the question object, I can access any of the properties of question by just using the syntax at question. That's the one. This is Rasor syntax, if you're not familiar with it, if you've never used Espie, not that pages before, but I can basically create a title. And then I've got in the second column I've got answer one and second answer two as buttons. And I do actually have on this version of the application I built, I had like previous and next buttons, but I don't actually use them in the real application because I don't want users to be able to switch questions. I want that to happen when the slide is changed by the presenter. So now this is the screen. It's exactly the same, but I just have effectively buttons there and what I need to do that is just basically wire those buttons up so they can vote. Now, this is the very first day that I had to do it, that is. I want to use WebSocket in my application now to get a WebSocket, I need to the browser to effectively the browser, the underlying browser to connect up to my WebSocket. You are now at the time when I first started building this, there was no way of doing that in C shop. There is now. So I can set up a WebSocket, a WebSocket connection and in C Sharp I can basically deal with the WebSocket all in C sharp. But this is showing you a mechanism that I had to to develop, which is basically called interoperability with JavaScript. So the version I'm going to show you now contains a lot of JavaScript and it kind of defeats the point of plaisir because I want to stay in C sharp all of the bit. I just built the UI, all of us in C Sharp, but this bit is going to be in some JavaScript and I'm not going to go too deeply into the JavaScript because I'm actually going to have to remove all of this, which is quite cool. But we've basically said is when the applications initialized, it's going to invoke some JavaScript, which is actually hided sitting in the in the index HTML page and basically connect over to this WebSocket URL. And when you when you do that, set up a reference, a dot net reference back to this application. And it's still got the same thing when it's connected. It's true, and then it says when all is connected, then. So basically, you will get a response back from the JavaScript and then R should be either true or false. And then if it's true, then it will be connected. So this website is connected that I load the sample questions in again. On the demand page, I had this piece of JavaScript interop dropping with, and it looks really similar to. Well, it's kind of painful because I've got a connection method, a disconnect method and a vote method. And basically the way that I'm doing this is I'm evoking this from C Sharp and C shops, creating the WebSocket, then invoking back the dot net method. When a message comes in and you'll see the dot net object reference invoke method on vote is then invoking C sharp method called on vote. And when someone votes it does, it passes this information across. Now this, this, this worked and I created a new method in my application on my API called vote. And basically now you can send this particular data over and say, I want to vote. Question one, answer one. And I was able to get into a scenario. Where I've created a new service function called Vote on the Server, it looks like this, you can see it later if you want. And the important thing is I had to do this JavaScript Interop just to be able to use a WebSocket. Now JavaScript Interop is really interesting in plaisir because there will be times when you're building Web applications that the thing that you want to build just doesn't exist in C Sharp and you have to invoke or work with with JavaScript. So you probably will find yourself having to dip into invoking JavaScript methods from C Sharp in your time when you're developing Blazier applications. But it's cool that we won't have to do this. We don't have to do this anymore. So let's just see what that looks like now. So I've got my application. It's connecting up to this websocket and when I click on Add to one, it sends a message. You can see on the over here you can see that there is a message that's being sent over via a WebSocket. And so the person within the screen can now vote using that. And so it's being sent to the lambda function called vote. And then that vote's being broadcast to all the connected clients. The only client that's actually listening to it, though, is the question screen, which is receiving all of the different votes and showing them on the screen as they happen. So now if I if I basically show that so I've got on the left hand side here the I've got the left hand side, I've got the question screen on the right hand side. I've got the vote screen. And you'll see as I'm voting on the right hand side, it's sending a message over to the question screen and we'll be able to see, like, how people are voting. Now, this is just tables and it looks a little bit ugly, but this is exactly the same logic is I had in my budget application that we used earlier and you'll see if someone's tapping and so forth and it's updating both sides. So that's the real time communication stuff is kind of now working. But how do we kind of remove the JavaScript? Well, I actually showed this talk in NBC London, and I was when I came to, like looking at plays, I was a bit disappointed about how quickly I had to jump into JavaScript to do something which was quite relatively straightforward. You see, when I do that, fetch questions beforehand and we don't make a request to get to get questions, we're actually underlying using the network stack of browser to go and get those questions is making a request. And it's getting routed now in in C Sharp. We're actually using the HDB client. But what they've done in the place that the Blazer team, they've kind of intercepted HTP Klein and wired up to the browser so that you can just use HTP client and all of your but your network requests are actually getting passed through to the browser. So it's using the networking stack of the browser. So that was really cool for HTTP requests. But WebSocket didn't work like that. We had to use this kind of invoking JavaScript to create WebSocket. But now they've basically wired done a similar thing, so they're basically intercepted the networking of WebSocket as well. So you can just create a WebSocket, as you would do ordinarily if you were building a C sharp console application and you add WebSocket to it. Or as an application, you want to have WebSocket to it. Well, now you can do that in a blender application as well. And basically the networking aspect of it is kind of wired back up to the browser. So you're really using the browser to do the network requests. But it looks, looks and feels like you're using C sharp and that's doing it for the C sharp. So to show you that, I'm going to take you to a more finished application that I have. So this is the razor question, questions that raise a few and you will see that instead of invoking JavaScript, what I've got. Is on the on initialised screen now, I say a wait websocket dot connect async, and obviously I do have the top here and I have sys system dot. Not that WebSocket. I'm using that library. And I've got a few other things as well that I'm using as well, New Nunziata, Jason systemd, threading and various other extoll things. I'm also using the client, which I'm having injected this what's not being injected? I'm just using the the instantiates. I'm creating an instantiation in the page itself. So I'm not using dependency injection. And I'm saying WebSocket dot connect, I think. I'm passing in a token because you can dispose you can basically cancel the thing using the token. And then I'm delegating it to receive loop, and what that means is that whatever this WebSocket receives a message, it's going to call receive loop. So that's now my website. This thing, this WebSocket is actually now a live websocket in my C shop application. And I can I can reference that. Do I use it at all in that page? No, I don't. On this one, I've got an echo that I don't and. One of my pages, basically, I can use in my view, I can say WebSocket State and if it's open, then I can show certain things and if it's closed, I can show other things as well. So you can actually it's just a C sharp object then, which you can use in your application, but it's intelligent enough to know what it actually underlying is the network communication website. So you're going back to the questions, not raise up. If this receive loop question. But all week. Steve Loopt. Let's show you on the screen, actually. So I set up the new WebSocket I call received loop as a delegate, basically when a message gets posted to receive loop on the screen. What happens is when the present changes the question, the current question in view, when they say, well, I want it to be question one or question two, that sends a signal up to the system, the system then broadcast that message to all of the connected clients. And that message ultimately comes back into this receivership. And what I do is I go, OK, I'm going to take the the WebSocket, not receive async information, and I'm going to receive this text. Now, it's actually Jassam, so I'm going to cast it as Jason is a Jassam object. I'm going to look for the message part of it. And if it's change question, then I'm basically going to change the question which is currently displayed on the screen. And change question, all that does is just that change question over here. Basically, changes to force changes, current count to the current question and then calls this thing called status changed, status change is an interesting one. You only you don't have to call that all the time. When you make modifications to your objects, there will be reflected in the UI automatically. But because this is using WebSocket, which might be coming back on a different I think it's coming back on a different thread or it's not always on the UI. Occasionally you might have the call status change to just tell your application that there needs to update the UI. I'm not really sure about the billing stuff about that and why you always have to call it, but I found that, of course, that changed to actually update the page. And so what this means now is. And just look at one of the browsers, I go over to the front end and. I'll take that one over there and just put that on that side. Well, look. And then if I just take one over here. Was it doing that? Sorry about this. So I've got the vote question on one side and the questions on one, and so hopefully. Yes, that is working as I change the screen on questions, you can see any one which is connected to the vote screen. The the title is changing as I'm changing the question. So I went to Tab's and Spaces, but everyone connected is getting the new question. And then I can answer and so forth. And all of that stuff happens over the signal. So my actual application I've just got a couple of minutes to talk about this is basically broken into a. A couple of sort of folders, I have my blazer front end, which is my my front end application, which does the WebSocket communications and allows the voting. And then I have a number of projects for each of my lambda functions. So I have an connect function and on disconnect function and message function and a slide function. And the way that I actually deploy this application, if I want to deploy it, is there is a folder, a file sorry. Inside. The back end forward deploy the the lambda functions, and here is something called serverless application model, you don't need to worry about what it is in Rayder and in Visual Studio. I can do this thing where I just basically. Right. Click on one of these templates and say deploy serverless application. And then the application I can deploy to to AYSO, I just say I want to update this and apply it, they can deploy and what it will do is build my application and it won't deploy it out to London. And then I'm able to sort of use this and publish it to life. The advantage I'd say over using this over the set up that I had before is that this only ever costs me money if someone like actually goes to my website and uses it and otherwise I don't pay for anything. The way that the costing works with LAMDA is that you only pay paper per request that's being served. You don't pay for the infrastructure which it runs on. So it's kind of that's kind of it. If you want the code, it's on my GitHub, I'm at the Beeb's on GitHub, I'm at the beach on Twitter as well. And I'll be developing this application and hopefully get to the same point that they look identical and they operate identically. And if you want to help me, then by all means, you can jump on that GitHub and start working with me as well. Thank you very much indeed.