00:01Okay. So good morning.
00:02I'm here to talk about real-time web applications with ASP.NET and MBC and SignalR.
00:10How many of you were in Dave's talk a little while ago?
00:13Most of you. Okay, good.
00:16I don't have a neck beard, so I rebuilt this in...rebuilt the app that Dave built using .NET stuff...
00:24...standard .NET stuff that I was comfortable with.
00:28But what are we talking about when we talk about real time?
00:31As Dave said, we're talking about data whose value decreases over time.
00:36It's the difference between knowing what is and what was.
00:40It's the difference between knowing where the zombies are and hunkering down in a bunker somewhere...
00:45...and getting dragged away to have your brains eaten.
00:50Real time is SMS. That's one that we're very familiar with.
00:53I use Google Voice on my phone, and maybe 15 months ago they were having problems...
00:57...and I was getting text messages anywhere from tens of minutes to hours after people sent them to me.
01:05That didn't work for me.
01:06SMS we expect to be real time or it's really of little value to us.
01:11Chat. That's a real-time app that we're all familiar with.
01:17We expect it to work in real time. Otherwise, we're going to send an e-mail.
01:21And that's almost real time these days.
01:24Stocks. Another use case for this kind of communication. It's kind of web app.
01:31Stock data decreases...the value of the data decreases dramatically over time.
01:38Weather. Tons of weather web apps out there. Few of them are real time.
01:46But wouldn't it be cool if more of them were?
01:49It would be a lot more valuable, at least for, you know, current conditions kind of stuff.
01:53Sports. Who's winning the big game? Who just scored a touchdown? Who just attacked in the big bike race? Who crashed?
02:02Auctions. I haven't been to eBay for a long time.
02:05I don't know if they're doing this kind of thing, but auctions are another use case where this would be valuable.
02:14You could see bids rolling in, in real time.
02:18Disaster response is a huge one that Dave talked about.
02:22We want to know where the injured people are now.
02:24We want to know where a building is on fire right now, not what was going on 20 minutes ago or an hour ago.
02:33Real time is not HTTP, though.
02:37The HTTP protocol on which the web was built was never conceived with real-time communication in mind.
02:45It uses...it's stateless. It uses a request response paradigm.
02:50Client issues are requested of the server, server response, end of story, maybe forever.
02:56The server...what we're really talking about is the server can't push data arbitrarily down to a client.
03:05And, you know, because HTTP wasn't built with that in mind, ASP.NET wasn't built with that in mind, at least partly because of that.
03:16But there are ways around this, right?
03:17We...even the most unsophisticated user knows, you know, you're at a weather web page.
03:24You opened it yesterday. You want to know the current weather, you refresh.
03:29That's not real time, though.
03:33You can kind of simulate this kind of thing by doing this sort of thing, simple polling with Ajax.
03:39Every 15 seconds, you do an XHR request, check if the server has new data for you.
03:47This gets closer to real-time communication, long polling, and this technique I think is used a lot...
03:55...and actually, SignalR that I'm going to talk about, is usually going to fall back to using this...
04:00...and I think Socket.IO and Node probably are, too, in most cases.
04:05You...the browser initiates an XHR request, and the server doesn't respond right away.
04:12It just waits until it has a reason to respond. It's got new data.
04:16And then either, you know, you get the data and do good things with it and then poll again, or it times out, and then you poll again.
04:30Server-Sent Events. That's sort of the next step beyond long polling.
04:34It's sort of a formalization of long polling the server, or, sorry, the browser takes care of most of the nuts and bolts of it for you.
04:43You just create the event source, passing it, the URL, to your end point, and then you listen for events.
04:51It's one way, only from the server to the client, but that's the problem, right?
04:55We know how to send requests from the client to the server.
04:59This is the problem, pushing data down from the server arbitrarily, and so this works a little bit...
05:08...another way that this is different from long polling is, when the server responds, the connection doesn't close and then reopen.
05:15It just stays open the whole time.
05:17I should back up actually.
05:19You know, this and this and, of course, this will work in all major browsers, including IE.
05:27This one works in all major browsers except IE, I think.
05:31I don't know about at IE 10.
05:36This is the next big thing.
05:37This is kind of what we're after.
05:38This is sort of the Holy Grail of real-time communication. WebSockets is a low-level TCP connection...
05:48...between the client and the server, full-duplex, two-way communication.
05:52It uses HTTP to kick things off, but then that part drops out, the part that can't do the push from the server drops out...
05:57...and you've got a TCP, full-duplex connection, client to server.
06:03All major browsers can do this except IE, until 10. At 10, IE will support this.
06:14But, the other thing is, ASP.NET doesn't support this until IIS 8, which has to run on server 8.
06:24There's other stuff. There's other ways of doing this, probably a dozen other ways...
06:28...forever-frame, which I don't know much about, but it uses an iframe...
06:32...and exploits some kind of arcane parts of the HTTP standard to...
06:38...that I think was intended for transporting huge responses in multiparts.
06:46So we've got varying levels of support in the browsers for the various different ways of pulling this off...
06:52...but, on the server side, this has not been easy to pull off in ASP.NET.
07:00I sat down, I don't know, a year and a half ago, when I heard about Server-Sent Events, I thought I'd try this out.
07:06And, so I wrote my nifty little code for the client side, thinking I knew how to do that...
07:11...and then when I started to try to do it on the server, I couldn't come up with anything at all, actually.
07:18I have heard that it's easy to implement on the server.
07:20I wouldn't know how to do it.
07:24But that's where SignalR comes in.
07:26It's...according to their website, it's an async signaling library for .NET.
07:30Cool. That's what we're after.
07:32It was written by these two guys, Damian Edwards, David Fowler.
07:35I don't know a whole about them, except they're wicked smart dudes, and they work for Microsoft.
07:41And they're not as cool as this guy.
07:44This is not Node. This is not Socket.IO. Scruffy hipster developer dudes are probably going to stick with that...
07:51...but I'm not a scruffy hipster developer dude. I'm an ASP.NET guy.
07:57Scott Hanselman says, It's a complete client and server-side solution with JS on the client and ASP.NET on the back end.
08:04Cool. What's important about that, I think, is client and server side.
08:10You get some nice bits for the server side that you can use to very easily implement your server-side end point...
08:18...and you get a nice handy client library to interact with it from the client.
08:27I say that, fundamentally, it's about pushing data from your server to your clients.
08:33That's the essence of the problem we're trying to solve here, and SignalR is cool because it abstracts all the messiness from you.
08:40You don't have to worry about which of those transports your...the browser your clients support.
08:45You don't have to worry about the nuts and bolts of how do I implement this thing on the server.
08:50SignalR does all that for you, and you don't have to think about it.
08:58In actual use, in most cases, it's going to fall back to long polling.
09:04See it...here it tried to do WebSockets.
09:06That's that WS there. It tried to initiate WebSockets.
09:10You'll always see an error as one script error, only one, we hope, in Firefox because it tried to do WebSockets...
09:19...couldn't, because my server doesn't support it, and fell back to long polling.
09:26And this, I don't know, to me this is kind of interesting to look at.
09:28You got a whole bunch of requests.
09:29Every request lasts two minutes, and then another one kicked off right away, it lasts another two minutes.
09:35It's just polling the server for two minutes at a time, waiting until the server has data.
09:41Then down there at the bottom, these two, you know, we're shorter.
09:45Either some device somewhere along the line saw that long connection and said, Uh-uh and killed it, or maybe...
09:53...probably more likely, the server sent some data down, got the data, did something with it, started another connection.
10:00Long polling. That's usually what it's going to fall back to.
10:06Let's see, they have a WebSockets transport that they're working on, at least as of November.
10:11They were working on it but still had problems with it.
10:14They've got a forever-frame transport.
10:16I don't know when they...under what circumstances they'd use that.
10:20They've got a WebSockets transport.
10:23As far as I know, they say it works well, but you need, again, IIS 8 on Windows 8 to do that.
10:31But what's cool is, you could build it now, deploy it on your IIS 7.5 server, and then when you get your shiny new IIS 8 server...
10:41...drop in the WebSockets component, and it should keep working.
10:46Only your clients that support it will now use WebSockets...we hope.
10:55So SignalR, like all good things, is on NuGet.
10:59How many of you are ASP.NET developers?
11:03Of those, how many are not using NuGet?
11:10Google it. NuGet's awesome.
11:13It's similar to what Dave was talking about. What do you call that?
11:18You just open up the package manager console and type install package SignalR or...
11:23...if you're a GUI guy, there's a GUI. You can pop open the GUI and search for stuff and click it to install it.
11:32But the SignalR package is a metapackage.
11:34It installs a bunch of stuff, notably, SignalR server, the bits you need to build your server-side end points and...
11:44...SignalR JS, your client-side library.
11:47It's also on GitHub, like lots of other good things.
11:54Now with SignalR, there are two ways of implementing this on the server.
11:59You got your high-level, easy, less full-featured hub, and you've got your low-level persistent connection.
12:09Seems to me to be a little harder to implement...little more...maybe a different programming model and, but more full-featured.
12:19I went for that one.
12:25We'll dive a little more deeply into the code, but just to show you how easy this is to implement on the server...
12:30...you implement, or you inherit from Hub, and then you...that's hard to read...sorry about that...and then, you know...
12:42...this function right here is what's interesting or what's most interesting about this.
12:46It's a function that somebody's going to call from somewhere, probably one of your clients, one of your, you know, a browser...
12:53...and then all you do, and they pass up, in this case, a lat/long and a zoom...
12:58...and then all we do is we call clients, which we have access to because we inherited it from Hub, .got map extent...
13:04...and send that stuff down.
13:06But, look at that. That's awesome.
13:08I didn't declare a .got map extent function anywhere on the server.
13:13It's a dynamic.
13:15I didn't even know you could do that.
13:16I've used dynamics to just hang arbitrary properties on them.
13:19I didn't know you could do this kind of thing.
13:21I don't know how they did it. I don't care. It's awesome.
13:24But what ultimately happens here is, the .got map extent, we're calling a function on our clients.
13:36And then this one is just a little less interesting, but, you know, in your hub...
13:39...this is how you'd implement just sort of a standard JSON end point, a get, get map points...
13:45...and it handles all...in both cases, it handles all the JSON serialization for you.
13:52On the client side, you got to include jQuery, of course, and then you include the jQuery SignalR library...
13:59...but then you also point it at your hub, and it uses that to get sort of a proxy...
14:09...to information about the methods that are available on your hub, so that you can call them from the client.
14:16And then some of your client-side code might look something like this.
14:19You, you know, you get a reference to your real-time hub, your hub, which mine was called real-time hub.
14:25You listen for those events, that .got map extent method right there, and you do stuff in response to them.
14:33And then you might also just call methods on them, like update map extent, right, if we look back here.
14:42So I was calling update map extent, and then everybody's going to get .got map extent called by the server...
14:50...pushing data down from the server to the clients.
14:53And then you can...and then, of course, I missed...this tripped me up a couple of times.
14:59I forgot to call start. You got to call connection.hub.start, and then you can give it a call back, what do you do...
15:05...hey, okay, what do I do when the connection is all spun up and ready to go?
15:09Well, I went and got all the map points that were there.
15:17So what do we build? How do we build it?
15:19The idea was sort of postdisaster triage, you know, fire over here, injured people over here, burning building over here.
15:31So we've got a web page. It's got a map.
15:36We've probably got a whole bunch of connected clients and some of them might be mobile devices.
15:41The fundamental idea here is, somebody drops a point on the map, and everybody else sees it in real time.
15:50So that's what it looks like.
15:51We built a desktop app, and we built a mobile app that should work on Android and iOS and, well, that's all there is.
16:03It might work on other mobile devices. We don't know.
16:07It's at SignalR.dts.agile.com. Don't beat it up yet.
16:11I want to do that actually. I want to know if it's going to...if we can kill it.
16:14But, first let's...just a very quick demo of how this works.
16:26So that's Dave. I'm not a Mac guy. So I lost my...there it is.
16:34Somebody's been having some fun.
16:36So there's...okay, so Dave is hitting this website from another computer, not this one that's hooked up to the PowerPoint...
16:43...and he's dropping some points on the map, and we're seeing them show up in real time. Drive it. Move it around.
16:48So he clicks...you got to click drive...oh, no, you are driving the map, of course.
16:52Yeah, and he's zooming now and panning and he's controlling my device and somebody else might be having some fun with us.
16:59Who is it?
17:01Okay, so, that's enough of that.
17:02We'll beat it up when I'm done in a couple of minutes.
17:10Yeah, thanks. I know. I'm...Macs.
17:17I want one.
17:21So I didn't do all the fancy bells and whistles that Dave did.
17:25I did add a point, drive map, that you just saw.
17:29So little more detail about how we pulled that off with SignalR.
17:36We used SignalR, jQuery, Leaflet, MicroEvents.
17:41It's not quite...I kept the feather, but it's not quite as light as Dave's node and Socket.IO one...
17:47...and that's mostly because of the jQuery dependency, I think.
17:50I tried dropping Zepto in, and SignalR didn't like that.
17:56So we used, you know, SignalR, jQuery, Leaflet because it light and fun and then that MicroEvents framework when...
18:04...well, we'll get to that.
18:07You saw most of this, you know, these are both methods that allow...that can get called from somewhere...
18:15...probably the browser, probably one of your connected clients.
18:21And, you know, we saw that first one.
18:23This one here, when somebody drops a point on the map, they call that method AddDamage location...
18:28...passing up a lat/long and a point type.
18:31We stuff it into our database using Entity Framework.
18:33I didn't use...Dave used a feature service.
18:38I have to do billable work, so I had to make this quick, and so I just stuffed it into a SQL Server database using Entity Framework...
18:47...and then we just echo that, broadcast that to all the connected clients we call.
18:52We basically call there, got new damage location method.
18:58I think probably a better way to describe that is, the got new damage location event is going to get raised on the clients.
19:07So Dave talked about this a little bit.
19:09He built this with some help from Brian and I guess a little help from me with Node, Socket.IO...
19:16...then we wanted to rebuild it in SignalR, so we took the bits that had to be different, SignalR versus Socket.IO...
19:25...and we abstracted them, sort of like behind an interface, our socket wrapper...well, our IO wrapper, actually.
19:37We just instantiate our IO wrapper, bind two events on it, maybe call some methods on it.
19:44And all the IO stuff, the SignalR or Socket.IO stuff, is hidden behind that IO wrapper.
19:50And here's what...at least, well, this is what part of the IO wrapper looks like.
19:56And you saw much of this code before, you know, we get our reference to the hub, we listen for those events...
20:04...and then when we get those events, we just raise another event, and that's using that MicroEvent library.
20:11When Dave and I hatched this plan, we wanted to use PubSub eventing to make this work in a loosely coupled way.
20:19So we went out to MicroEvents.com? org?
20:25Google MicroEvents, or not MicroEvents, sorry, Microjs.
20:28It's a website that has dozens, hundreds, I don't know, of Micro-Frameworks that do various things, animation...
20:37...dom manipulation, eventing, pretty much anything you could imagine.
20:42And we found this MicroEvent, a tiny little MicroEvent framework that allowed us to do the PubSub eventing.
20:51So that's what's going on with the trigger and also with the mixin, you know, MicroEvent.mixin.
20:59And then, of course, we start up the hub here at the bottom. Don't forget that part.
21:04In the callback, we just go ahead and get all the points, and when get them, we raise an event to add them to the map...
21:10...or to tell the, you know, tell the application to go ahead and add those points to the map.
21:18So pull out your device at SignalR.dts.agile.com and let's see.
21:23I'm really...this is running on a VM back in our office in Fort Collins...
21:28...and I'm curious to see if it will stand up under, you know, a load.
21:34So hit it. Excuse me?
21:41Yeah. It should be still alive. Yeah, there we go. Okay.
21:49[Audience comment] So I'll drive it.
21:50Come on, more. Yeah, nice. Alright.
21:57Are you driving? Is anybody...
21:59[Audience comment] I can drive, yeah.
22:00Yeah, drive the map a little bit. Is it working on everybody's? Is it moving around?
22:04[Inaudible audience comment]
22:08Nah, it's just a demo, we didn't...
22:09[Audience comment] Yeah, we didn't do delete.
22:11It would be delete star from...
22:14[Inaudible audience comment]
22:17Sorry. [Audience question] If we have a [inaudible] mail code error.
22:20[Audience comment] Oh, yeah.
22:21Oh, right, right.
22:22[Inaudible audience comments]
22:28Right, yeah. Yeah, we kept this very, very simple.
22:32[Audience comment] I just asked.
22:33Right. Yeah. So it seems to be standing up pretty well. Alright. I like it.
22:45So that's all I have.
22:46Oh, wait. I do have a...wrong way every time.
22:54[Audience comment] Three fingers. I know, but, I just go the wrong way.
22:59There it is.
23:02Oh, yeah, this code is not...what just happened?
23:07This code is not on github yet. I'll put it up tomorrow or maybe Monday.
Real-Time with ASP.MVC and SignalR
Mike Juniper of DTSAgile demonstrates an application that keeps data in sync in real-time, without requiring an update or page refresh.
- Recorded: Mar 29th, 2012
- Runtime: 23:13
- Views: 1493
- Published: Apr 30th, 2012
- Night Mode (Off)Automatically dim the web site while the video is playing. A few seconds after you start watching the video and stop moving your mouse, your screen will dim. You can auto save this option if you login.
- HTML5 Video (Off) Play videos using HTML5 Video instead of flash. A modern web browser is required to view videos using HTML5.