>> Well, good morning. Good afternoon. Good evening. Depending on where in the
world you happen to be. My name is Christopher Harrison. Welcome to Web Wednesday, the show where I bring on
people that are much smarter than me to talk about
cool things, web dev. Today I'm actually very pleased
to bring back on Anthony Chu. If you haven't already seen Anthony present or just talk
about technology, he's fantastic. He's absolutely brilliant. He's really passionate
and knows probably more about doing serverless codes, serverless computing, and Azure
functions than I will ever know. He's always just a
fantastic guest to have. Today he is coming on to talk about a really cool little
service called SignalR. If you're not familiar with SignalR, what SignalR allows you to do, is to do real-time messaging. That way, if I want to maybe enable chat or if I want to
do something where I've detected that an event has
occurred on the server and I want to be able to send a message
down to a browser-based client, then SignalR can do those
types of things for you. It's a really neat both
SDK as well as service. It can also help simplify
doing what would typically require a fair bit of code
if you are going to do this natively using WebSockets. But you didn't come here
to hear me talk about it. You came to hear
Anthony talk about it. Let me bring Anthony on. Anthony, thanks again for joining. It's always wonderful to have you on Web Wednesday to chat
about anything and honestly, it's always fun to chat with you. >> Yeah, thanks for having me back. Yeah, I had a great time last time. Yeah. Looking forward to this. >> Yeah. Me too. Because I know that you've got a really cool demo
that you're going to take us to in a few minutes. Let's start here. What is real-time messaging? What does this mean in the Webspace? >> In the Webspace,
we're typically talking about things like WebSockets. But in the early days,
there wasn't WebSockets. The first thing that
we probably did 10, 20 years ago was just keep pinging a server to see if
there's any new messages. Quite inefficient, but
it gets the job done. Then we figured out
new ways of doing it. There's a technique
called Long Polling, where you open a connection
to the server and the server doesn't respond until there
is a real-time update. It's a little bit more
efficient and keep pulling all the time
over and over again. Then for a while there, and I
think it still exists right now. There's a technology
called server-sent events, that you can also use to
push real-time messages from a server to a client like
a browser or even a mobile app. Then in the last five, 10 years, WebSockets
is gone everywhere. That seems to be what
everyone is using these days. You can actually work with
WebSockets pretty easily just by using this plain JavaScript in the browser and
connecting to a WebSocket. But a library like Socket IO or SignalR which
you're talking about today is actually like an abstraction on
top of it, I guess you can say. What that means is that instead
of actually working with the raw web sockets and actually
working with the frames, sending frames to the server, getting frames back from the server. You're actually working on
one or two levels above that. You end up doing things like sending messages from the
server to your client. Very much like you are just pushing a message to a
queue or something like that, or even just doing like a remote
on a procedure called thing. It's a lot more natural. Then you can also have access
to higher-level concepts, you can put a
connections into groups. Or just basically
create arbitrary grips. Instead of keeping track
of whichever your users, which have connections happen
to be from say, Seattle. Then you only want to send a
message to only people in Seattle, without a library like that, you have to manage all that yourself. Then when you need to send it,
you actually literally have to iterate through all the
different socket connections, WebSocket connections and
send these messages down. Whereas with both Socket IO and SignalR and other
like libraries like it, you're literally just
make a call and say, hey, send this message to this group
and then it just does it. A lot of the group and user
management, it's all done for you. Another thing that stuff
like this will do for you is that you don't have to worry
about what my clients, whether it's could be
a super old browser. It could be, a fairly
old phone device that might not actually
support WebSockets. These libraries will
actually fall back to the other methods
that I mentioned before, like server-sent events,
we have a Long Polling. You still program
exactly the same way, you say send a message, but it figures out for that
connection which protocol to use. You don't have to worry about it, and then reconnections
and stuff like that. >> That way if for whatever reason my browser didn't support
WebSockets that it's still able to funk down to an earlier technology and guarantee me then I'll be able to "Send" a real-time message
even if it's not actually doing it with a real-time stack. >> Yeah, exactly. >> Okay. >> Yeah. >> We've mentioned that the
WebSocket is this cool, new thing. What is WebSockets, and how does
that compare to HTTP or HTTPS? >> Yeah, so it's a
bidirectional protocol. You can actually send messages
from the server to your client, but clients can also
send messages upstream. That's really the main difference. If you look at the
actual protocol itself, you go very deep into
the differences. But for day-to-day use, that's really all you
really need to know. You're sending these
frames back and forth, down this bidirectional channel. >> I'm just going to simply say HTTP, but as opposed to just
like normal HTTP, where what I'm going to
do is I'm going to make a request via post getter
or whatever it is, and then get a response back. Then once that's done, then we basically tear down
that connection and that's it. With WebSocket that it sounds
like I'm going to be able to almost treat it like it's on my network
from what it sounds like, as if I was just able to just do a little TCP signal
to it only instead obviously, it's a web-based protocol. Where now I'm able to send
a message up to the server, and then the server is at some later point able to send
a message back down to me. >> Yeah, exactly. >> Okay. All right. I can get behind that. SignalR then, you mentioned
that it's an SDK, that that's something that can
help make it easier for me to start programming with WebSockets. >> Yeah. It's an SDK that came
out of the ASP.NET world. You actually don't need ASP.NET to use it now that's we have a service, and that's what we're actually
going to talk about today. We're going to talk
about how we can use JavaScript and Python code running
in serverless functions and Azure Functions to work with SignalR service to basically get the same capability
in other languages. As an SDK, I think there's multiple languages that we support in terms of clients. So web is obviously covered
with JavaScript and TypeScript. But there's also, a Java client, there's the C++ client and throughout the community there are
different clients that are produced in open-source
for things like Swift and Python, and
things like that. >> That's interesting. So
then from a client-side, I'm not bound to only use a browser, that I can also be using a
fat client like I could be using a phone app or I could be
using a desktop application, and still be able to
communicate with SignalR. >> Yeah. It's quite
flexible that way. You've got to mention mobile. One of the things that
people quite often will get confused by a little bit, when talking about WebSocket
technology is that this is not the push notifications on your phone that we
typically talk about. That's typically very
specific to whether using Apple or Google
and stuff like that. That's totally separate
from WebSockets. WebSockets is when you
have your app open, say you open up a map, for example. For instance, you're
looking for a car share and you see the little cars moving around the map,
that's probably WebSocket. But when you close the
app and you exit out, and then you get a notification from the app
saying that your driver's here, that's typically a push
notification that sent another way. That's not what we're
talking about today. >> Then I guess it also bears highlighting the fact that
this is also different from those browser notifications that
everybody is going to say no to that that's not what we're talking about when we're
talking about WebSockets. >> Right. Yeah, WebSockets is
not annoying like that, no. >> Okay. Cool. WebSockets is really about being able to maybe
create a chat application or that maybe there's a long-running process like maybe I'm placing an order
doing something like that. The server's now going
do a few things. It's going to take maybe 15, 30 seconds, a few minutes, and then now it wants to let
me know that that's completed, that it can do that with WebSockets. I'm also thinking maybe if I'm watching or if I'm
following a sporting event, and somebody has scored, if I've got the page open, then it can refresh the page then or update that piece of
data using WebSocket. >> Yes. Exactly. There's just
so many uses for it now. We don't even think about it anymore. When you open up a web page, just expect things to just happen without you pressing
the ''Refresh'' button. I think we pretty much
take that for granted now. >> Yeah, I'd agree with that. Zimbabwe Dungeon Master, which is a great name, asked the question, ''Is SignalR good for server
to server communication, say for an old project, whether its no gRPC." >> Yeah, I think that
should work fine. You obviously have the
weigh the pros and cons. You definitely have the
[inaudible] due to the protocol. So as long as you own both sides, it's typically not too bad. If you cannot, if you want external services to connect
to your service quite often, like an old-fashioned HTTP
REST API type of thing, it'll be easier for
other services to use without binding yourself to a specific library like
SignalR or Socket.IO. It works well for that purpose. I've seen people use it, for generic API for service, we do typically see people
fall back to using HTTP APIs. >> That makes sense. Again,
the key difference is we're always looking for the need
for two-way communication. If all that I need to do is make
a request, I get a response, and I'm good with that, then we can just again
go back to HTTP. It's really if I'm looking for that ability to have
two-way conversations. Now, you mentioned
the SignalR Service. What is the SignalR Service? >> It's a service in Azure
that basically makes it really easy to use SignalR
without you needing to write an ASP.NET
app and creating it. Or spinning up Express
app and using Socket.IO, and they have access to a library, like Socket.IO or SignalR. So you can spin up an instance
of SignalR Service in Azure, and there's actually a free tier so you don't have to pay for anything. You can use it for up to like 20 connections or something like that, which is plenty for a lot
of apps, and that's it. You don't have to worry about
managing anything like that. Your clients will connect to that, and we need to send messages to your client behind the scenes
if your using Azure Functions. There's actually some output
bindings that you can use in Azure Functions that
makes it super easy with a single line of code to
send these messages out. You don't even need to
figure out how to talk to the service behind the scenes. We just do everything for you. >> Since you mentioned
Azure Functions, I'd be remiss if I didn't then
ask about Azure Static Web Apps, which if anybody's not familiar, Azure Static Web Apps is
probably the best thing that we've released since
Visual Studio Code, which I know is a bold statement. But it gives you that ability
to run those types of applications where the bulk of your code is going to
be on the client-side, which is really how we do
modern web dev these days. That you get that and
your server-side code using functions in one
very nice, neat package. I'm guessing then that the
SignalR Service would be able to work then with Azure
Static Web Apps as well. >> Yeah. Hopefully,
we'll be able to show you an example of that running
an Azure Static Web Apps, actually working with the
authentication in Static Web Apps. Like the SignalR team always makes
fun of me for doing chat demos, but I will show you a chat demo. I do find that with chat
it is overdone in a sense, but also it is probably
the easiest concept. I'll not explain to you
what a chat app is. I'll just show you the code. I think it's a good way to
show you how SignalR works. Then we'll go into other things. I do find that show you some
more interesting stuff, though. >> Yeah. You know what, there are certainly those stock standard demos
that everybody goes to. But sometimes, everybody goes
through it for a good reason. Now, what's great
about that chat app, like you said, is not only A, does everybody know
what it is, but B, it makes it really easy
for me to be able to demo. I don't need to do anything fancy. I just type something here and then poof something
happens over here, which is really the effect
that you're looking for. >> Yeah. Should we take a
look at how to do this? >> Actually, I'm going to throw
in one last question from Andrew Ha about SignalR Service, ask if it's instance-based
or serverless? >> It's instance-based right now. Although I think it's a
pretty common request for them to offer
consumption-based pricing, so per connection.
Currently, it's not. If you need to go over that, there is a fixed Instance
price that you go up to. I'm not sure whether or not
they support auto-scaling yet. You do pre-provision these
things called units, and each unit gives you like
a thousand connections. But I know it's definitely
on their roadmap to see if they can support
consumption-based pricing. >> Then Egoist asked if SignalR requires an implementation
using Async/await . >> No. I think those two concepts are
probably a little bit orthogonal. Yeah, there's nothing like in SignalR itself that
requires Async/await. >> Okay. >> Yeah. But typically, most of the SDKs do return
promises or tasks in C-Sharp, so you end up using
Async/await with it. But I don't think
there's anything that requires you to use Async/await. >> Okay. Fair enough. >> Yeah. >> Let's take a look
at some code here. >> I think the first thing
we're going to do is because it's going to
take about a minute or two just to create a SignalR
service, let's do that. I'm in the Azure portal. It's fairly easy to do. I'd search for SignalR and then
I'd say I want to new thing. I'm just going to go and create
a new resource or webwednesday. Maybe I'll call it webwednesday. >> Very creative in the names. I appreciate that. >> I try my best. Actually, when I code or well, now as a PM, I code less. Naming is the thing I hate the most. I always ask someone else for naming. >> I feel that. >> I'm going to pick a
location nice and close to me. Then I'm going to pick the free tier. Hopefully, this is big enough.
I'm trying to make a pick here. >> There you go. >> There's the default and classic. I don't need to explain to you what they are because we're
not using them today. We're going to use a serverless one. That's the one where we can
use with Azure Functions. >> Okay. >> Then I'm just going to
go ahead and create it after the button lights up. I'm going to go off and get created. I think in probably a minute
or two, we should have one. >> Okay. >> While that's happening,
let's take a look at how we can work with
it from Azure Functions. >> Let me actually sneak in
a real quick question here. Zimbabwe dungeon master
asked the question, how big is the message buffer? Is it per hub or per group? >> The message buffer? I guess it really depends on
what we mean by message buffer. I think in the past, SignalR has had the ability to support like when you disconnect accidentally or on
purpose or whatever. When you reconnect, the messages that you missed will
get replayed to you. Well, not really replay because
you never got it the first time. It will get sent down to you.
There used to be a buffer there. I believe in the latest
versions of SignalR both are really memory intensive and
also really hard to get right that we stopped
supporting that. Typically, the pattern that
I see people use and I'll show you later on a more
fuller-blown web app, is that when you reconnect, you go and reach out to
a different endpoint. Or maybe when you reconnect, on connection, that the server, or in this case, a serverless
function will actually send you the latest updates. >> Okay. >> For instance, for a chat app, when you connect, the first
thing you do is say, "Hey, give me the most recent chat
messages so that you can repaint your screen and then
start listening for new ones." That seems to be a more scalable and easier reasonable way of supporting buffers versus actually creating a buffer for every connection and then worry about how to get
rid of it and stuff like that. I hope that's what
they meant by buffer. But if not, please ask. >> Okay. That sounds
good. Let's build an app. >> I'm going to assume a little bit of knowledge of Azure Functions. Even if not, I'll try to walk
through a little bit of it. In Azure Functions, the first
thing that you need to do is create what's called an app
and then within an app, you can have more than one functions. These functions are serverless. I'm going to be running these
locally on my machine right now and then some of the other demos I'll show are actually going to be
running in the Cloud. >> Okay. >> First thing, I'm
going to do is I'm going to say create a new project. This is using the Azure
Functions extension and VS Code. I'm going to choose this
folder that I already created. I will use Javascript. Let's see. What should I do? I need to switch to a different set of templates
so I can see everything. I'm going to choose
this thing called a SignalR negotiate HTTP trigger. It's a really long name. Funny enough, I think I added this item to this
menu and I named it. See, I shouldn't be
trusted to name anything. I'll quickly talk about what
the negotiate thing does. You can ignore it when you
first get started with SignalR. For basically the browser
or the client to figure out where your SignalR service is, it needs to first call an
endpoint to figure that out, and that's what the
negotiate endpoint does. It's actually part of
the SignalR protocol. The first thing that it does
is it's actually going to make an HTTP post to an endpoint. By convention, it needs to be named negotiate with
documentation and all that. But then you don't have
a do a heck of a lot in an Azure Function app
for this to work. You can see that using a template, we already created an HTTP function. This function will just become
an HTTP endpoint in the Cloud. Because the route is negotiate, it's going to be at
slashed, whatever HTTP, whatever domain name I get for
my function app slash, API, slash negotiate and soon our service will just
know how to talk to it. I'll show you that piece
of the code in a bit. Then down here, we're basically getting access to this thing called
a connection info. What this thing does is that
it gives you this payload that you need to return back to the client so that it
knows what to do with it. Again, you don't have
to worry too much about how this works because most of it is done for you
in the bye-bye to templates. But you do need one of these things. Typically in here, if you need to
assign a connection to a group or you need to associate a
connection to a user so you can send messages that are only
going to be received by a user, you might need to do a
little bit more stuff in the negotiate function. But typically if you just want to do a broadcast to everything
that's connected, you don't really have
to do anything here, it's going to take everything as is and that's that. Should I run it? I'll run the
whole thing in a bit later. The other thing that I
want to show you now is with a negotiate function, what that allows the browser or any client to do is to
connect to SignalR service. Actually, the real thing
that your app wants to do is actually, when something happens, whether it's because you receive an HTTP request into your function app or your function app could be
listening for queue messages, for example, and then every
time you get a queue message, you want to broadcast that
out over your WebSocket. Or it could be a change over
Cosmos DB or if it could be a change in blob storage and basically, any trigger
that you can set up. In Azure Functions, you
can basically turn around, and when one of those events happen, turn around and send a message to all your connected
clients over SignalR. I've seen stuff, for instance, moving stuff around in a map. Imagine you can an event every
time an airplane moves in the sky. You can actually take that
and broadcast that out to browsers and then you
can actually paint that plane moving on a map, so things like that. It's pretty flexible. But for our purposes here, because we are building a chat app, I will just create an HTTP endpoint. How do I do that? Say Create Function and then I just
want an HTTP function. I'm going to call it messages
and anonymous is fine. We don't need security for a demo. Let's see. What should I do? This
is just a plain HTTP trigger. It's going to become an
endpoint as /API/messages. The idea is that every time
we want to send a message, we can post to this endpoint. The body of the message will be
the message itself, I guess. >> Okay, so people then aren't going to call the negotiate directly. They're going to do everything
then through this Azure Function. >> Yeah. This is the thing that
actually does most of the work, which is relaying a message from
one client to everybody else. It'll make maybe a little
bit more sense once we fire it up and see it run. But what we need to do now is we need to use what's called
an output binding for this. I can say Add a binding. I want an output binding, and I want a SignalR binding. Then the naming thing again. I'll call it messages or
new message over that. I'm going to say default
here, but I'll tell you why. SignalR has a concept of hubs. You can actually divide a single SignalR service
into multiple hubs. So you can try and think
of them as namespaces. If your app happens to support both, like a real-time chat
kind of a thing but another part of your app might support a little
real-time notification, little like changing the number of messages that appear in the corner of your screen
or whatever it is. You can actually have two
different hubs we call it to take care of each of
those types of messages. You don't have to worry about using a single hub in figuring out whether this message is actually
a chat message. This one is actually a notification. You don't have to worry
about any of that. You can divide it up into
multiple namespaces. I'm going to call this one a default and I'll tell
you why in a sec. Then I need to just
give it a setting name. I'm going to call it
AzureSignalRConnectionString. Absolutely long name. >> That absolutely is going to
be on the server or in Azure, I shouldn't technically say on the
server because it's serverless. But that's where it's going to sit there and it's going to store then the location of that
SignalR server, correct? >> Yeah. It's going to
be a connection string. It's going to conclude
both the location of it as well as a Get key. >> Okay. >> Then the app setting value, I'm going to skip that for now because I need to figure
out what that is. I'll probably want to
do this off-screen because I don't want to
show you what that is. Yes, that's done there. Also another long name. Again, I came up with that name. Basically anytime
you see a long name, I probably has
something to do with it because I couldn't figure
how to make it shorter. >> I'm okay with long names. If it's something that's going to be automatically filled
or especially if it's something that there's some form of an autocomplete or IntelliSense, long names are okay. I would much prefer a longer
name that describes what it is, than a short name where I'm
having to figure out what the world it's supposed to do. >> Okay, that's good. I named
this binding newMessage. In here now I can pretty
much get rid of all of this. The first thing that
I want to do is get access to the body of the request. I'm going to say const, just message equals
request.body, I think. Well that'll give me
basically the body itself. I actually don't really want
to do anything with it. You can do some validation in
here if you want or you probably should because anyone can
send anything to this thing. But again, demo, no security. I'm just going to relay this back
to all the connected clients. In order to do that, I
would have to talk to the context which gives
me some bindings. Then for newMessage binding because that's the name I gave
the SignalR output binding. I am going to assign it to an object. I can actually assign it to
an array if I want to send a pile of messages out all at once, I can actually use an array of these objects, but
I'm only going to send one. So I'm just going to
just have an object. This object takes two things. Again, this is all in documentation, so you don't have to worry about
memorizing it like I have here. The first argument, I
guess that it needs, it's sync all the target, and that is really
a name of an event. I'm actually going to
call newMessage as well. Plus this is an event's name. You don't have to worry about
too much why or what that is. Then the arguments is an array. Then I'm just going
to pass the message. That's only going to have one
argument, but it can have more. >> Okay. >> That's it. That's
really all the code that we need to send that message. One thing that I'll do here. >> Really kind if breaking the
case for using TypeScript here. Because then I could create the interface for what
newMessage is going to be and I can then of course know what my rack is because I can add in
the Typein to know all of that. If you haven't already
started using TypeScript, you should definitely use TypeScript. >> Yeah, I'm okay with TypeScript. I think we had this conversation
last time about how I have, I won't say love-hate
relationship but I'm like I can go both ways. I like the simplicity of
the JavaScript as well. I'm just going to create
a very simple HTML page here as we're chatting that show you how to now use an HTML page to connect
to SignalR service. I'm going to do a couple
of things before that. In my local.settings.json,
this is where we configure that Azure
SignalR connection string and this is where I'm going
to type off-screen here. I'm going to whoop go over here. But that still leaves us here. I'm going to go over here as well. I'm going to go over
to, actually, I'll show you what this looks like. My resource is created. Then see, I'm going
to click on "Keys". Okay, I'll be back. Then I will
copy the connection string. I'll get out of the keys. I'll give them back to there. I'm going to paste in
my connection string. I'm going to save it, and I'm going to bring this
thing back on this side. You can see that I pasted into connection string and
you can't see the key. >> Perfect. >> Now all this serverless, server-side stuff will work because that key is there or
that connection string is there. I'm going to quickly
do one thing here. I'm going to go to this
JavaScript CDN called JSdeliver. There's actually better
ways of actually acquiring the SignalR SDK for JavaScript. You can NPM install if you
have a full-blown React app. But I'm just lazy. I'm going to search Microsoft
SignalR. There it is. I'm just going to browse to the
browser version of the thing, and I'm just going to copy the HTML. All that's going to give me is a really simple script tag
that brings in SignalR. But like I said, if you're
using React or [inaudible] , really anything that compiles, you would be referring
to NPM package instead. >> Wasn't there an ASP.NetCDN
for quite a while? >> Yeah, there is. >> Is it still there? >> One of the things
that we wanted to do with SignalR, and this
is quite a while back, is that we wanted to couple it
from ASP.Net so that people don't get the false impression
that it's only for ASP.Net. >> That makes sense. >> Yes, this actually used
to be scoped to @ ASP.Net, but we changed it to @Microsoft just to make it a little
bit more agnostic. But there probably
is an CDN somewhere. JSdeliver is actually a really
easy way to really have an http endpoint to
any file that's in NPM package or even in a GitHub Repo. It does all that stuff for you. So you can just reference it. Quickly I'm going to show you
what what you get to do here. I'm going to go and say const, connection, equals
newSignalR.HubConnection. This is where
IntelliSense will come in if you actually use an NPM package. I don't get that, so
hopefully I'm doing it right. >> I am going to bring you
over to the dark side. I want to bring you
over to TypeScript. >> Yeah. I'm going to put /api here. What this means is that I'm
telling the SignalR library that my hub endpoint is
going to be at /api. Then by default it's
actually going to attach /negotiate at the end of it, the figure of what the
negotiate [inaudible]. That really works is that
just by saying /api it will find the right negotiate
endpoints that I created over here. Then I can also say
something like with automatic reconnect so
that you don't have to worry about what happens if
the connection drops momentarily. It'll just do the reconnect for you. The last thing I'm going to do is I'm going to say .build. Then I'm also going to
go connection .start. This thing returns a
promise if you're going to want to wait for it and see. They say connected or
whatever you can do that. I'm going to be lazy and not do that. The only thing I have to do now is that I've established
the connection. What I want to do is listen
for that new message, I guess. The then new message event so
that I can do something with it. I'm going to say
connection.on newMessage. Then I get [inaudible]
function in it and then the message is that argument that
I passed on the server-side. Then I suddenly do something with it. I'm going to be lazy and just be
like console.log(msg). That's it. But you can imagine
this updating the UI and doing something way more
fancy than console log. But I think this should
more or less work. I'm going to go ahead and you mentioned the Static
Web Apps earlier. Static Web Apps we're
actually working on a local emulator
experience so that you can actually serve a locally spin up as single server that both
spheres your static assets, as well as starts up
the functionality. Basically, the two parts
of a Static Web App both working together at a
single endpoint locally. So I'll be using that to
start up my app here. My app consists of my
Index.html plus some functions. I think I'm in the right place. I'm going to say Static
Web App, swa, starts, and I want triple w as
where my Static Web App is. Then I want to say,
I hope this works. My API is here. So that works. Oh no. We're already running this. I'm going to find my browsers. It's over here. Oh, it is. That's the next demo. Here
we go. Is it going to work? >> That's funny. >> Starting up Azure Functions, it's also starting up
my front end as well. So I can go to this
4280 endpoint locally. I'm actually going to
open up my console because everything's going
to be happening in there. I'm going to go
localhost 4280. Oh, no. An action argument is required. This is the unexpected part. One second. Connection equals new
SignalR Hub Connection Builder. How do I know that? Apparently,
not enough time though. There we go. Don't ignore that
fav icon thing, that's fine. >> Yeah. >> I'll quickly show
you what happened here. If we look at the network. Let me make this full size. What we've done is that we started with a thing
called the SignalR thing. But you can see that
we're making a request to the negotiate end-point and this negotiate endpoint actually comes back with a couple of things. The location of the SignalR Hub
or business SignalR service, as well as a token that the
SK can use to connect to it. You don't have to know
anything about this at all. This is like behind-the-scenes,
how it works. >> Okay. >> Then it's going to go,
now you can see that it took that endpoint and
it's now calling it. I don't know if you can
see it on the mouseover. >> There we go. >> I may do it and maybe not because I don't know how much I'm sharing. Sometimes it's not coming through. >> No. It's all coming
through just fine. >> Okay. Great. Then this last
one here you can see that this is the final WebSocket connection that's made after it's connected
in that negotiation dense. This is the only thing
that we really care about. If you look down here, you
can see some messages. I'm going to hope that this
thing is actually working. >> If you go back to that real quick, there was one little thing that
I wanted to highlight there, go to go back to that WebSocket. The protocol there is different, it's WSS which is WebSocket
secure like HTTPS there, but that's you saying WebSocket is
a different protocol from HTTP. >> Yeah. Typically you start from HTTPS connection and then you upgrade to a WebSocket and
that's what's going to happen here. >> Okay. >> Cool. I'm going to take a look at the messages that are
coming through here. I don't know how to make it bigger. You can see that it
stops coming down, the search just pings
from the server to make sure that we're still connected. I'm going to go back over
here and just really quickly make an HTTP request to it. I'm just going to do it.
You can [inaudible] for it, I'm going to just do
it within VS Code. I'm going to say POST
http://localhost:4280/api/messages. How do we know that?
We've gotten that before. Content-Type is application JSON. I'm even over with that. Then I'm going to pass just
like hello world message. >> Hold on. What are you doing here? I've never seen this in VS Code. >> This is an extension
called HTTP REST client. What it allows you to do is basically type the HTTP message and click it. Then you can see that it worked. Now if I come over here, you can see that I got that WebSocket
frame as well in my console. I got that thing printed out. >> Yeah. >> That's how it works. I don't know what else I'd show you, but I guess I can do more, I can open up multiple browsers and you can see that they
all receive the message. But at its core, that's how you create the functions that are needed
for you to support SignalR. Then also a webpage that
makes that connection, it actually listens to the messages. Now it's really just up to
you and what you want to do with it. That's it. >> Okay. >> Then I can show you a more
full-blown version of this. What's a good way to do that? I can go to GitHub. Not
that. Let's go to GitHub. >> I'm still stuck
on that REST client, I'm blown away by that extension. It's now immediately
going to be my favorite. >> That's nice. I can commit those
things to my source control. >> Right. >> It's great. I was
quickly going to show you how you can turn this
into a full-blown chat. [inaudible] is another function app, but it's got the same negotiate
endpoints nothing special there. I think that even the send
message is about the same. It does a little bit more because this is running in Static Web Apps. It's actually going to
parse the headers to figure out what the actual color is, the user detail so they can't
spoof that, they're logged in. So I'm pulling out their
user detail and I'm actually setting that
as their sender. Basically sending the
sender to that username. You're securely sending
these messages. So when you see the server saying
this message came from Anthony, it really did come from Anthony. But aside from that, it's
really the same thing. Remember the target
and arguments thing, doing exactly the
same thing as before. Then there's actually one
more thing that we're doing is that my function.json, I have an output binding
for table storage as well so I'm saving these
messages as well and that's done by this line of code. Visit this line of code and
this line of code will seize the message to a
storage or to a table, as well as broadcast
the message everywhere. It's really easy to use. Then like I was talking about before, when you first connect, you need
to get the message history. I have an HTTP trigger table basically saying give me
the latest 50 messages. Then the code is really
one line of code, I'm just going to return all those
messages back to the browser. I think we have maybe 20, 30 lines of code in the server-side. That's going to be everything that
you need for this app to run. Then I'll show you the HTML as well. This is using view so
just a lot of HTML stuff, but really down here you'll
recognize the connection stuff. You'll recognize me setting up
a listener for the new message. This is [inaudible] ,
I'm posting my endpoint. Authenticated user,
don't worry about that. A little messages history. When you first startup, we're going to make a get
to the messages endpoint. That's going to return
message in the table. That's really all it is. I guess there is a standard view out. Then if I go to chat
on anthonychu.com, you might already be
logged in, [inaudible] . Let me log out. There's
a Static Web App. >> That log in, log out that you're using is that's
something that's built into Static Web Apps or you're
using the Graph Toolkit? >> This is actually completely
from Static Web Apps. I didn't really have to do anything. When I click this
button, I'm actually literally just redirecting to the login endpoint
for Static Web Apps. >> Okay. >> Because I'm already
logged into GitHub it's going to bounce right back. You can see that I'm logged in. I tested this four months ago, but still works, testing. You see it works even if I copy
this and open up a new browser, paste that in, come back over here. Say, "Hi", You can see that
both browsers are good. It's really easy to do and it works. So that's how build a
real-world app with it and it's really straightforward to deploy
this to the Static Web Apps. >> Okay. Then I can go and
sign in with my GitHub. Of course, I'm going to need
to MFA real quick here. Chaga, chaga, chaga, boop, boop, boop, boop, boop, boop, boop. >> I'm excited and I'm waiting. >> I'm going to authorize
it, grant consent. Anthony now owns half of
everything that is mine. It worked, there it is. Very cool. >> Nice. That is awesome. I wasn't sure if that
was going to work. I don't know why. Maybe it's because I wrote it so who
knows what's going to happen. >> I had full faith in you. >> Maybe in the last, 5-10 minutes, do you want to look at a couple
of other non-chat examples? >> Yeah. >> If there's any questions feel
free to pass them to me as well. >> I'll show you that Python one. That's right here. There's not as quite a
few different apps in it. I have an Azure Functions app and you can see a negotiate endpoint. The only difference is this
is now written in Python, but it's basically the same
thing. Let me close that. It looks exactly the same. >> People are logging in
and sending messages. >> Oh, no. Well, at
least I know you log in. >> I know. Yeah, it's all good. >> I haven't built a
moderation feature yet. I just have another one here, that instead of listening to HTTP, I'm listening to Event Hubs, which is like our high-scale events hub or event bus
type of thing in Azure. The idea is that I'm simulating
how we could potentially have maybe a Python script running
on a bunch of Raspberry Pi's, that are just taking temperature
readings or whatever kind of readings and just shooting
that off into Event Hubs. Then on the other end of it, it's going to trigger this function
and this function is again, not going to do a heck of a lot, it's just going to relay basically
the payload from the events, which in this case is some fake temperature that it
read from some fake device, and just relay it off
to connect to clients. >> Okay. >> But I want to use
this to show that it's not just limited C-Sharp or
JavaScript, it works in Python too. >> There's nothing
that's fancy there. It's just reading off of
the event and then using JSON loads to convert the JSON
into a Python dictionary, Python object, and then you're just returning that
back using JSON dumps. >> Yeah. Really it's not doing much and this one line of code sends
that message to everybody. That's the function app,
I don't think there's too much to show you there. I can skip the device simulator, it's just a fake script for me to just randomly generate temperature, a couple of times a
second, and just shoot that down to Event Hubs. Then I'll show you
the SignalR client, which is a Python script. It's 20 lines of code
or something like that, but you can see very similar code
that you saw, make a connection. Every time I see a new message, I am going to write it
to my screen and I've got the library that I use,
it's called terminal plot. Basically, it looks like this, looks like it's still connected, so maybe it still works. Actually, I'm going
to stop it for now, because I got to start everything up. I think I talked about everything. I'm going to go ahead and
start my Azure Function app. Oh, no, something is using that port. Stop. I need to go stop this. >> It's probably your last time demo. >> Let me stop this, stop that, go back over here. See if this works. >> I did notice that SignalR
core is just available as a normal Python library so
you just PIP and install. >> Yeah. >> Cool. >> Someone else created this, so it's not an official
Microsoft library, but it works pretty good
from what I can tell. I don't know why I closed
that, I meant to go over here. My function app is up, so now it's time to send some fake messages. Just shooting some fake messages out. Then if I flip back
over my function app, you can see that it's
actually running. Then I can go off into my terminal
now and I'll restart my client. You can see the little
messages coming down here. >> Okay. >> Yeah, it's painting
it onto the screen in probably 1970s fashion. If you squint you might see a graph. >> No, I can start to see
that that's coming together. >> You have end-to-end, both the thing that's
sending the messages, the function app itself, as well as the thing that's
listening to SignalR messages, all working in Python. If that's your thing, you don't
have to learn anything else. >> I dig it. Okay. Well, we'll
get Jim Benedict into this since he's all about IoT and Python. >> Actually shout out to, I don't
know if you know Dave Glover, but he actually helped me with how to send messages from
a Python script. So shout out to Dave. >> That's fantastic. If people wanted to learn more about SignalR or if they wanted to learn more about Azure Static Web Apps, where would they go to
find said information? >> Actually this thing is
really distracting me. I'm going to stop that. >> That's right. I switched back to a dual-screen so you're all good. Okay. Good. I don't even
have to show you anything. Microsoft Docs is a
great place to start, especially to use SignalR
Service with serverless. In the SignalR Service documentation, we have basically Azure
Functions examples for every language that we support. If you want to learn more
about how to connect to it and actually do stuff with it, SignalR has a bunch of
docs on how you can use their different clients as well. But if you start off from the
SignalR Service documentation, we should have links to everything, including some quickstarts that
you can build your own chat app. >> Actually I just found
it in the background. This is pretty robust and I'm not saying that just because I work here, I'm looking through and
there's a whole bunch of tutorials which I really like just because if I can just see the code a lot of times then I can
figure the rest out from there. I really like the tutorials
and I really also dig that there's a testing and
debugging part as well. Not that anybody ever writes
code that requires debugging, but just in case it happens >> Yeah. >> That's fantastic. How about for learning more
about Azure Static Web Apps? >> Again, Microsoft Docs
is a great place to start, but we also have a bunch of courses
or modules on Microsoft Learn. We also have a Microsoft
Learn module on how to use SignalR Service with
Azure Functions as well. With that one, you build
this thing with Cosmos DB, like a pricing database, so you can see a bunch of prices. Then if you update
something in Cosmos DB, it instantly gets reflected in the
browser. So that's pretty cool. >> Look at that. Storing
that into chat right now. That's fantastic. Very cool. Where can people find you? >> I don't know. You want my home address? Is that
what you're looking for? >> I was assuming
your Twitter handle, which is right up above your head. >> Is it over here? Yes, here. You can chat with me on Twitter, that's probably the
easiest way to find me. I'm sure there's different ways
to GitHub, things like that. >> Too funny. I love it. At some point soon once
COVID is no longer a thing, I'm going to have to
get up to Vancouver, we'll have to go get
dinner at Kissa Tanto, which is one of my favorite
restaurants in the world. >> Nice, that's awesome. I never heard of that place. So you're going to show me
around Vancouver. It's awesome. >> It's spectacular. It's a
Japanese-Italian fusion restaurant and it all comes
together really well. >> Nice, I'm sold already. >> Beautiful. We will
make that happen. All right, Anthony, thank
you so much for coming on, chatting about SignalR. You are going to be back again
in a couple of three months to talk more about Azure
Static Web Apps, which I'm super excited
about because again, that's one of my favorite things. Again, best thing we've
done since VS Code, although that little REST HTTP thing, that extension, that
might be the new one. But anyway thanks again for coming on and showing us all about SignalR. >> Thanks for having me
on. It's a lot of fun. >> Beautiful. I love it.
Thank you to everybody for tuning into Web Wednesday. Next week we're actually
going to have Cassie Breviu on who's going to
talk about Babylon.js and how you can do cool MR things all inside of a
browser with JavaScript. I'm super excited for that. Join next week and every week where we're chatting with smart
people about web dev. Thanks again for tuning in. Bye. I want that button, there we go.