 Hello, everyone. Welcome. I'm so excited to be here because today.NET Core 3.0 has shipped, which means Blazor is now available for production use on the server. In this talk, we're going to talk about using Blazor to build full-stack web apps using just.NET and C-Sharp. Now, .NET has always had a great story for building server-rendered web apps. These are apps where you stick some .NET code on our server, and that code generates HTML or JSON in response to browser requests. If you wanted to do anything on the client in the browser, well, that meant you had to use one of these guys. You had to write some JavaScript. There's lots of great things about JavaScript, but there's also some additional cost and overhead of having to bridge these two very different developer worlds with different languages, different frameworks, and different tools. Well, this is no longer the case. You can now write your client-side web app logic using .NET with Blazor. Blazor is a client-side web UI framework where you get to write .NET and C-Sharp instead of JavaScript. You write UI components that encapsulate your UI logic using C-Sharp and Razor. You can then share your .NET code, the same assemblies on both the client and the server. If you've got some validation logic, you can use it on both sides of the wire. If you need to call into JavaScript code, you can still do that. You should have access to all of the JavaScript APIs of the browser and other libraries through a JavaScript interrupt mechanism. Now, Blazor is in large part made possible thanks to a relatively new open web standard called WebAssembly. What is WebAssembly? Well, WebAssembly is a byte code for the web. The idea is that if you can compile your code to WebAssembly, it can now run in any browser on any platform at near native speeds. We've been working for a while now on getting .NET to run great on WebAssembly. We are building a .NET runtime in WebAssembly. This is how a Blazor WebAssembly app works. The browser provides the core WebAssembly support. On top of that, we've built a .NET WebAssembly runtime. You then build your Razor components that could compiled into normal .NET assemblies. They're downloaded with the runtime into the browser and then executed directly in the browser. The browser then sends all its UI events to your .NET code, your components run, they render their UI, and Blazor does all the hard work to figure out what exactly changed in the UI. The difference is then sent back to the DOM and updated very efficiently. Now, the cool thing about Blazor though is that you can host it in multiple different ways. We've talked about running your app on WebAssembly, but alternatively, you can also run your Blazor apps and host them on the server using the same components. The way a Blazor server app works is your components run on the server. The browser sets up a real-time signalar connection with the server. That's what it uses to handle and send all of the UI events that the user is creating. When a button click occurs, it gets sent to the server, the corresponding component runs just like it did on a Blazor WebAssembly app. The component renders that the Blazor does that hard work of calculating a diff. It serializes that diff back down that real-time connection back to the browser so it can be applied to the DOM. So in .NET Core 3.0, we've shipped support for Blazor server apps. You can use that in production today, go and download it and install it. I was thrilled that we announced today in the keynote earlier, that Blazor WebAssembly apps will be shipping and supported in May of next year. Now, how do you pick between these two different hosting models? Well, there are different pros and cons to each. A Blazor WebAssembly app, that is really a true single-page app. It has full interactivity. It runs client-side on the user's device. You can use all of that user's device's resources like its CPU, its memory, its storage to the extent that the browser will let you. It supports offline scenarios. You can deploy it as a static site. You don't even need to have .NET running on the server because your app is just a bunch of static files. You can build progressive web apps with Blazor WebAssembly. The downsides of Blazor WebAssembly are, well, you need to download that runtime with your app, and that means an additional download size costs. So your app may load slower. It does also require that the browser supports WebAssembly. And while all modern browsers do, if you need to support something like, say, IE11 or an older browser that doesn't have WebAssembly support, then this one's not going to work for you. Also, Blazor WebAssembly is still in preview. It's not ready for production yet, so that's a factor to consider as well. Blazor server apps, they have a really small download because the only thing they need to download is a little piece of infrastructure code that sets up that real-time signal R connection. Your Blazor component code is now running on the server, on a full .NET Core runtime. And it has access to all of the resources that the server has access to. If you want to talk directly to the database, you can do that from a Blazor server app. Some people really like that your code never leaves the server in a Blazor server app. If you're uncomfortable with the idea that your DLLs will get downloaded into the browser and the user can grab them and decompile them, then maybe a Blazor server app will be a better choice. It can really simplify your architecture to not have to stand up additional WebAPI endpoints and so on in order to access server resources because you're already there. You're running on the server. The cons of the Blazor server model are, first of all, latency. All of your UI interactions are going to go over the network. So you're going to want to make sure that your clients and the server are as close together as possible. There's only so much you can do about the speed of light. It's a connected model, so obviously no offline support. And also, you're paying with your server resources to run the UI for each connected client. So that's an additional scale and cost consideration. How do you get started with Blazor? Well, I recommend going to blazor.net. That's where you can find all of the getting started instructions and the Blazor docs. You're going to want to install .NET Core 3.0. If you're interested in playing around with Blazor WebAssembly, you'll need to install the Blazor WebAssembly template too. If you're on Windows using Visual Studio, make sure you get Visual Studio 2019, 16.3, which is now available today as well. If you're a Mac or Linux user, you can use Visual Studio Code to do Blazor development using the C Sharp extension. And we are working on Visual Studio for Mac support for Blazor as well, and it should be coming soon. All right, let's take a look at Blazor. Let's write some Blazor code. So I'm going to go into Visual Studio. And I have here the same Blazor weather app that you may have seen earlier in the keynote. This is a single page app that lets us see the current weather of Seattle, where we're close to where we're currently at today. As you can see, as usual, Seattle, it is raining. All right, so that's pretty cool. And we didn't really get a chance in the keynote to take a look at how this app is running. And this is the same app. I did refactor it slightly to move all the components back into the app project just to simplify things a little bit. Let's take a look at how this project is structured. The first thing to notice is that a Blazor server app, and this is a Blazor server app, is just an ASP.NET Core application. Here's the program CS file for the app. It's got the normal ASP.NET Core hosting boilerplate code in here. It has a startup class that defines the startup logic for the application. In this configure services method, this is where we define all of the services that we want available through dependency injection for our app. Up above, you can see that we're adding the services for both Razor pages and Blazor server, which is interesting. Blazor, remember, is a client-side UI framework. It does not replace or remove the need for the other server rendered frameworks. You still want to be able to run code on both the server and the client, Blazor's for the client. These two pieces of technology are meant to be used together. And we'll see more about that in just a bit. This app's also setting up an HTTP client to be used to talk to the backend weather forecast service that you saw Glenn build earlier. And then we have some other app-specific services that we'll talk about in a bit. Down below in our configure method, this is where the app's request handling pipeline is being set up. Most of this code is boilerplate. It's the same set of middleware that every ASP.NET Core app has. The two things that are different is here you can see we're setting up the Blazor Hub. This is the SignalR Hub that Blazor uses for managing all of the UI interactions with the browser. And then lastly, there's this map fallback to page route. What is this all about? Well, this is going to take any request that makes it to this point. And make it go to slash underscore host. It will basically reroute it to this endpoint. What's that underscore host? Let's go take a look. Well, underscore host.cshtml is just a razor page. Remember, we're using razor pages and Blazor together, both sides of the wire. Most of the content in this page looks pretty normal. Looks like normal HTML. But there are two things that are kind of different. The first is at the bottom, there's this script tag. This is where we're adding the blazor.server.js script, which is provided by the framework. This is the script that sets up the real-time SignalR connection with the hub that we saw previously. We also have this HTML helper, this render component async call. What is this doing? Well, this is rendering the apps route component right here on this razor page for the initial render of the app. And there's nothing special about this app component. This could be any component you want. And you can render any component you want onto any MVC view or any razor page. Let me show you, this is really the case. I have a different project over here, not the weather app. This is just a vanilla MVC app, an ASP.NET Core MVC app. I just did File New Project. And then I added those things that you just saw from the Blazor server app. In the startup class, I added server-side Blazor. Down in the endpoints, I added the Blazor hub. We don't need the fallback route in this case because we're not going to be using routing. We're just going to be having individual components on the pages. And then in the app's layout, which I think is under here and shared, there it is, you can see down here at the bottom, I've also added the Blazor server script. So we should be all set to go to use components in our MVC app. Now I've added a component to this project as well. It's right here, component1.razor. It's pretty simple. This namespace is important for getting all of the web-related razor directives to light up. So if you're having problems with those directives not compiling for some reason, make sure you've got it using for this namespace. It's needed. And then we have an input and a p tag. And we're using this at bind directive. What is that? Well, that is setting up a two-way data bind between the value of the input and this message field that's on my Blazor component. And then I render out the current message down below. You can also see that I'm changing which event is used for the bind. Normally a bind on an input would occur on change. Here I've decided to do it every time I touch the keyboard on every key press on input. So I should see this message update with every keyboard press. Now to add a component to a project, it's really easy. You can just do add, new item. And there's a razor component item template that you can use. That's what I use to create this component. OK, let's now add this to one of my views. I'm going to go to the home page of this app. And I don't remember the HTML helper. So I'm just going to copy it. Let's go grab this piece of code and put it right there in my MVC view. I don't want to render the app component. I want to render my component, one component. Components are just normal .NET classes. So that's why you can just use the type name. The type name comes from the name of the file. OK, that should be it. Let's go ahead and run it. And we should see a vanilla MVC app with the normal default template styling. And hopefully a component. Let's see. Yeah, there's my component. Let's let's zoom in a little bit. And if I just start mashing other people like hi.NET copy, you can see it's doing the data binding. We have an interactive component on an MVC view. Blazor. OK, great. So that's using Blazor from MVC apps or Razor pages apps. If you have an existing app, which I'm guessing many of you do, you can use Blazor with that app. There's no need to rewrite an app to be Blazor. You use Blazor for your client-side concerns. OK, let's go back to the Blazor weather application. We've seen, I think, everything in underscorehost.cshtml. Let's look at that app.razor component. Here it is. This is just setting up client-side routing for the application. It's going to find all the routable components in this assembly. Let's go see what routable components we have. Well, it turns out we only have one. And that's this forecast.razor component. You can tell it's routable because it has the app page directive at the top. You do need to explicitly specify the route. At some point, maybe we'll infer that from the file path. But for right now, for Blazor components, you need to explicitly specify it. OK, so there's only one page in this app. So this truly is a single-page application. And then down below, for most of the rendering logic for the forecast page, it's just razor syntax, a mix of HTML and C-sharp. Like this get background class function is returning some code for a class based on whether it's daytime or nighttime and what the current temperature is, if it's a warm temperature or a cold temperature. So just some C-sharp and HTML. Now, some people get kind of concerned because down here, at the bottom, we have that code block again. And there's all this code that's in my component. Some people get concerned about this mixture of code and markup. And is that really OK? Whatever they used to say. You're supposed to always separate those things. And you should separate code from your components if that code is like business logic. But if it's related to the presentation layer, it's perfectly fine to have it in line in the file. I mean, it's going to be compiled into the same class anyway. But if you still prefer the code behind pattern, that's fine. You can do that too. If you remember from the keynote, in the forecast page, we have this little temperature picker component. Let's go look at the app. That's this guy right here. If I click it, it switches the temperature unit from Celsius to Fahrenheit and back. That component's implemented over here in the components folder. And it's pretty simple. It's got a div and a couple of spans. But it does have some code. If you don't like that code living in the component, here's how you do it. You're going to add a new class. You're going to call it the same file. TemperatureUnitPicker.Razor.cs. And if you did it right, it should nest nicely underneath. It did. All right, great. And then I usually call. This is going to be an inheritance model. The code behind will be a base class. So I usually call the base class the same name as the component with base. And it needs to derive from component base. Let's get the namespace for that. Good. And then you can just copy all the code out of the code block. Put it into your base class. Save it. We do need to change the visibility of this private method because this is an inheritance pattern. So now it needs to be protected so that it can be visible by the derived component class. And then let's just inherit from our base class using the at inherits directive. So that inherits the temperature unit picker base. OK? And that's what you do. And if we wait a second, hopefully all those red squiggles will go away as it picks up the base class. And there it goes. OK, so that's how you can do code behind if you pattern. I prefer the inline pattern. So I'm going to keep that. I'm going to delete what I just did and leave it the way it was. All right, great. So that's that. Let's look a little bit more forecast page. Now, I made some changes to some files. I have to reload the browser. Now, one of the things that's not so nice about this app is that the location is hard-coded. You only get the weather for Seattle. It'd be nice if we could actually see the weather for some more places. Maybe we could search for a location or maybe even use the current location of the user based on their browser. How can we add that? All right, so let's try and add some location search capability. Let's add it using a component. So I have a location search dot razor file over here in my components folder. And this is going to allow the user to search for places. And it's got some very simple markup, very little. It's got a div with an image. This image is just a little search icon that shows if a search query is in progress, like a little spin, a little spinner thing, if you're currently searching for locations. It has an input. And this input is a list-driven input. The data list for this input is defined below. And then we are binding the value of the input to this search query property, very similar to what we saw before in the MVC app. We're binding on every single keystroke. What we want is every time the user starts typing, we're going to kick off a search and try and autocomplete for them with this text box. Now this search query property is pretty clever. It has a setter that if the search query value is not null or empty, then it's going to do this search debounced method. What is that guy? Well, you probably don't want to do a back-end request with every single time the user types on the keyboard. That might be a little bit too chatty. So instead, this is going to debounce, which means it's going to wait for the user to sort of pause typing and sort of see if they're done. And so there's some clever code in here. It's using a cancellation token source. And it cancels the previous search if there was one in progress and then does a delay. And it keeps checking to see if the search was canceled while it's in the process of doing this query. And here you can see here's where the weather forecast service is being asked for the current location or locations based on the text from the query. And then if it still hasn't been canceled, then it saves the set of returned locations to this location field, which is just a location array. And that's what we're using to generate the data list that the user can then pick from the location text box. Cool. Now the user needs to also be able to pick a location. And so that's what this on change event handler is for at the end here. On that same input, when the user actually selects a particular location or hits Enter, then this location selected method gets called. What is this doing? Well, it's getting the selected location. And then it's raising a callback so that the parent component can know what the location was that was chosen. This location change property is of type event callback. It's a component parameter, which means it can be provided by the parent component as a piece of code to call when this event has occurred. All right, so let's wire up this component in our forecast page. So let's go up here. And we're going to do right under here, let's do location search. Location changed equals location change is the name of the method I have defined already on the forecast component. All right, so now we should have a location text box. What does this component do when the location actually changes? Well, it cancels the real time updates to the weather that were in progress previously and then kicks off another async for each loop to get new updates for the new location. So that's what it's going to do. If we go back to the app now, hopefully we can see this working. All right, so now we have a text box. So let's try and type something. So let's try like Chicago. All right, we get our dropdown. We can pick it. Let's try New York and our little spinny things working. Great, so that's working. So now we can search for locations. But I'd also like to be able to just use the user's current location. Have them use the browser's native capability to detect the user's location with its geolocation APIs. That would be cool. But those APIs are in JavaScript, which means I'd have to write some JavaScript. And I don't want to have to write some JavaScript. Blazor does have JavaScript interrupt capabilities. You can call from .NET into JavaScript and back. And it does a lot of that for you. That's how it manipulates the DOM. So I could write my own. I could use the same abstractions. But fortunately, most of the time, you don't actually have to do that because someone in the Blazor community has already done it for you. So I've added a package to this application. Let me look at my new packages. Here's the install packages. You can see I have this ASP.monsters.blazor.geolocation package. This is a package that was actually written quite a while ago in the early days of Blazor. Here's the URL for the GitHub location. The code was a little stale. We had changed the APIs a bit and it broke this package. So I had to fork it and fix it up a little bit. But pull request was submitted. So hopefully any day now, that will get merged. And this package will then be up to date with the latest Blazor release. But I'm just going to use this package to call the browser's geolocation APIs. Here's the code for that package so you can see what that looks like. That's TypeScript. Let's not look at that. Let's look at this G sharp. OK, here's the location service class provided by this package. And you can see it's taking an IJS runtime service. That's provided by Blazor for doing JavaScript interop. And the way you use it is by calling invoke async. And invoke async takes a string, which is the JavaScript function that you want to call. You can pass in additional parameters as .NET objects that will get serialized and sent over to JavaScript. And then the generic parameter is the return type. So that's how you can call into JavaScript. Fortunately, I don't have to do that because I think it's Simon Timms is the guy who wrote this project. That's great. He already did it for me and he took care of writing all this complicated JavaScript. So that's awesome. I don't have to do that. Let's go back to Blazor Weather and use his package instead. So I've already installed his package. You may have seen in the startup class I added his geolocation service. I put an alias for it to call it geolocation service as an injectable service in my app. And then in the location search component at the top, you can see I'm at injecting the geolocation service so I can use it. All right, where do we want to use that? Well, when this image, this is the third image, that's that little target button. When it is clicked, we're going to call get local weather. What does that method do? Well, this method is just going to call the geolocation service and get the geolocation. And then it's going to use the weather forecast service passing in the latitude and longitude to resolve that to a location that we can then use to update the weather. So hopefully that just works. Let's go back to the weather app. If I click on the target, you can see the browser saying, do you want to allow this app to use your current location? Yes. Let's see where I'm currently at. Where am I, really? I'm in Redmond. That's actually correct. And that is the correct weather for Redmond. All right, so that's how you can get the current location. Using an API that's actually written in JavaScript. But as far as I'm concerned, it's likely it was written in C sharp. I'd also like to be able to pin some of these locations so that I can go back to them instead of having to keep search for them. How could we do that? Well, I wrote a little push pin component. There it is. And this is just a custom check box that I got the markup from over the web. It has an is checked parameter and is checked changed event callback. And this has been styled to look like an actual push pin. So let's go ahead and put this onto our forecast page. And where should we put this? This will need to go. Let's put it right by the location. Push pin. And we want to say is checked. We're going to bind that to the current location. And it has an is pin property so that we can tell whether it's been pinned. And then let's wire up the event callback to call our pin location method that I've already defined on the forecast component. So if we go look at pin location, here's what it's doing. It's keeping track of all the pin locations in just a collection. And then keeping track of which pin location was shown last using this pin location index. Now we also need some buttons so we can cycle through those locations. I've already got those defined here. So I'm just going to copy them in. Let's see, where do we put those? Let's put them by the image. And I like the little carrots on either side of the image. These are just two little carrot images that, again, have on-click handlers defined. When these handlers are called, it just changes what the current index is of the pinned location. All right, so if we reload the app now, hopefully we should be able to see a little pin icon. You see that right there? We should be able to pin Seattle. Let's do a Honolulu, Honolulu. That looks good. Yeah, let's pin that. And then, oh, it's not, did I do that? And then let's, oh, and it's not showing up. Why am I not showing up? What did I do wrong? I forgot something. When I get back to my notes, would I forget? The pin location is there. Oh, did I not save? I always forget to save. Ah, yeah, I didn't save. Go back. And I helped save for the pin, but not for the actual UI so I could cycle through. So Chicago, no, let's pin this one. So pin Seattle, Chicago, and let's pin that. Yeah, now we got our icon so we can cycle through. OK, so you get the point. So there we've done some Blazor development. And that sample will be available up later for you to play around with. Now, obviously we don't have enough time to go through all that's available in Blazor. I highly encourage you to go check out our Blazor workshop where you can learn to build this awesome British pizza store. And that will teach you all about the different parts of the Blazor component models. A big shout out to our component vendors, Tellerik, DevExpress, Syncfusion. They've built wonderful Blazor component libraries that you can use. Radzen's also a component vendor. And they ship a low code solution where you can build Blazor apps with just a designer. It's pretty awesome. You should check that out. Another big shout out to our Blazor community. Thank you, Chris Sainte, who has provided us packages for local storage, which is actually part of this sample app, and also Simon for the geolocation APIs. If you want to check out lots of great projects in the community, I encourage you to go to awesomeblazor, aka.ms slash awesomeblazor. It's a GitHub repo that keeps links to all different articles, videos, tutorials, samples, and libraries. One of my favorites is this Blasteroids sample. I'm just going to show it really fast. And then I'll get off the stage. Blasteroids is a Blazor WebAssembly app. I think it's hosted on GitHub pages, but it is doing a full version of the 1980s Asteroids app written in .NET on WebAssembly. That's pretty awesome. All right, that's all I've got. Blazor server is available today. Download and install it, and start doing full stack development with .NET and C-Sharp. Thank you. Awesome, Dan. Thank you so much. That was so cool. OK, so we have a ton of questions and excitement about Blazor. Where should we start? How about, oh, which one did we have? They jumped around again. No, things are moving. We had one picked out. We promised. Well, here's a question. I don't remember where it is on the screen, but it was a question about browser compatibility. Are there any browsers that we need to worry about? Is this something that works everywhere? There it is. For Blazor on the server, it works with all the modern browsers. As long as you can set up that WebSocket connection. For older browsers, you may need some polyfills to get it to work, but those polyfills are available, and a lot of them are maintained by the community. For WebAssembly, you need a browser that supports WebAssembly. So if you don't support WebAssembly, you're kind of out of luck. So like IE11, you're not going to be running Blazor WebAssembly apps on IE11. Gotcha. All right, so I can't find Blazor project templates in Visual Studio for Mac. Any idea when we'll be adding those? Yeah, Visual Studio for Mac is coming. We are working with them on that. It's expected in the next Visual Studio for Mac updates. They're busy trying to unify all their code with Visual Studio and get all the common infrastructure in place. So they're taking, took a little bit longer for them to get their tooling in place, but it should be coming very soon. But you can use Visual Studio code in the meantime. Can Blazor work with backends that are not.net? Absolutely, like if you have a Blazor WebAssembly app, it is just a bunch of static files. You can host it on GitHub pages. You can put it on Azure static site hosting and have whatever you want on the server. It could be Java on the server. It could be Python. It could be a fast typing monkey. It doesn't really matter because it's just a bunch of static files that's going to be downloaded into the browser and run client-side. Okay, so then this question, what kind of host do I need for Blazor? You could put it in Azure Storage and make a static website. You could use Jekyll. You could put it in on GitHub pages. You are non-denominational. For the WebAssembly version, yes. For the server version, that's an actual ASP.NET Core app. So you're going to want to have actually servers at that point. That will run on the server. Like we're going to set up a SignalR connection with the server. We highly recommend using the Azure SignalR service actually with Blazor server apps because they will handle connection scale out for you. Nice. All right. So next question. What's the underscore generated file when you created the code behind the base class? Great question. That's just an artifact of how the tooling works. In order to drive the IntelliSense, there are multiple passes of code generation that are occurring. We actually hope in a future release to clean that up a little bit so you don't see those generated files quite as often as you do today. Part of that is involved with us making the generated components partial classes, which is coming in.NET Core 3.1. Excellent. What else do you think? We have several questions. Let's do a refresh and see if there's anything more. Any ideas about how any web socket connections server-side Blazor can handle? Well, that really depends on how your server is set up. If we use the Azure SignalR service, it will multiplex all of the connections to your app and you can scale up to tens of thousands of connections, no problem. The connections may not be the real bottleneck though. Most likely it's going to be like memory on the server because you are paying with your server resources to actually run the UI for the client. So you've got to maintain all the UI state and the component instances running on your servers. So you're going to have to plan for that accordingly and we have docs to help you do that. All right. Very cool. So what's the progress and website size and there are a few complaints that it's too high? The size of the website? Yes. Yeah. So Blazor WebAssembly is bigger. You have to bring a runtime with your app. There's a WebAssembly file. Right now a default Blazor WebAssembly app like with our project template weighs in at about two and two and a half megabytes compressed. Things that we're doing, we're improving the IL linker so we can strip out more code. Right now we only run the IL linker on part of the app. We're going to run it on more. We think we can trim down the WebAssembly file itself. There's a bunch of tricks that we're looking at. We've even talked about like taking the DLLs and stripping out all the PE headers and stuff like that. So that stuff doesn't need to be downloaded. We have a bunch of tricks that we're going to look into. But to be clear, it's still just about a megabyte or two and is that compressed? Yeah, that was the compressed side. Honestly, I've been to a lot of people's websites where they have a PNG on their homepage that's that big. Like 10 megabyte PNG. And you can cache the file. So you can put it on a CDN and how people only have to download those once because most of the time that runtime is not going to change. It's the same runtime no matter how much you're iterating. We love you, but we have to go. There we go. All right. So next up is Xamarin Forms. We're writing beautiful and more productive Xamarin Forms than ever with David.