 Hello. So welcome to the building Blazor applications on a Mac. Definitely check out the Weather app that Scott Hunter just mentioned. It's really cool, but we have some kind of simpler stuff to get started to talk more about what Blazor is and take you through an intro app. How to get your feet wet and then we'll move to a more realistic app and make some changes there as well. Yeah. Oh, and I'm Kendra Havens. I'm a Program Manager on .NET and Visual Studio and. I'm Dan Roth. I'm a Program Manager on the ASP.NET team. Cool. Okay. So Dan, what is Blazor? What is Blazor? There's so much talk about it. I know. It's so much excitement. So Blazor is a modern web framework for building client-side web apps using C-Sharp and .NET instead of JavaScript. It's cross-platform, it's open-source, and it's based only on open web standards. Ooh. Now, we've had ways to build web apps with .NET for a long time. Traditional .NET web app, you take your .NET code and you put it on the server. Then the browser sends requests to your server and it responds with dynamically generated HTML or JSON. That's pretty typical .NET web application. But if you wanted to do anything that ran in the browser, well, that meant you had to use some JavaScripts, like using whatever the popular JavaScript framework of the day is. That's cool. I mean, JavaScript is great. I mean- Yeah. It's great. You have to switch contexts though and that can slow you down. So if I can stay in .NET code. That's convenient if we can use that same tool belt and the same language, the same frameworks, the same tools, same build system across your entire application. That's what Blazor is all about. It's enabling you to build full stack web apps using .NET and C-Sharp. That's what we've been working on. Sweet. Okay. So Blazor, you build client-side web apps using just .NET and C-Sharp code. It also comes with a component model. So you can build reusable web UI components. You can package them up as Nougat packages and libraries and share them with your friends. It also enables you to use the same code on both sides of the wire. If you have some common logic like validation logic, or data models that you want to use both on the client and on the server, you can do that with Blazor. It's full stack web development with .NET. At the same time, if you have existing JavaScript code or you want- Sorry. So we're sharing .NET code. So even working in F-Sharp or Visual Basic if I have libraries that I want to call from Blazor. Yeah. You can do that. It's just normal.NET assemblies that you're calling into your Blazor application. Absolutely. Also, if you have JavaScript, you can still use that as well. You can call into existing JavaScript libraries from your Blazor code and even call back from the JavaScript code back into .NET through JavaScript interop. You can use that to also leverage all of the native functionality of the browser. Okay. So if I'm slowly migrating my app to Blazor, I try and it out in some section. I can still use JavaScript at the same time. Don't have to throw your JavaScript away. You can just reuse it in your existing Blazor application. How does that work? How is that possible? I know. It seems like magic. Well, there's two ways that Blazor apps function. The first mode we call Blazor server. The way Blazor server works is that we set up a real-time connection with the browser. We use SignalR to do that. It's basically a WebSocket connection. Brady has a talk on all on SignalR later today. All about SignalR later today. Definitely check out that then. Once we've got that real-time connection with the browser, we run your Blazor UI components on the server. Any UI events that happen in the browser, we send them over to the server, dispatch them to your components. The components run, they render, and then Blazor very cleverly figures out just the parts of your UI that have changed and serializes that diff back down to the browser to then be rendered and updated. So it's a thin client model. You're still running your UI components on the server, but you get that rich interactive feel that you would expect from a JavaScript-based single-page application. Okay. In server, all of my C-Sharp is compiling on the server still, not at all inside the browser. All the compilation happens at build time, but your build code is going to be running on the server on .NET Core. It's not actually going to execute in the browser. Right. But you still get the rich interactivity of being able to handle all the UI events and update the DOM seamlessly without having to do a full browser refresh. But I have heard about things that would have allowed you to do that. Yes. Not compiling, but executing. Executing, that's right. In the browser. With Blazor WebAssembly. Blazor WebAssembly. What we do is we can download with your app a full .NET runtime that's implemented in WebAssembly. Now, WebAssembly is an open web standard. It's basically a byte code for the web. If you can compile your code to WebAssembly, that code can now run in any browser on any platform at near native speeds. Native as in like browser native. Well, pretty close to the wire. Like it's almost like an assembly language that's been standardized for the web. So it's pretty fast. Super fast. It is fast. So we built a .NET runtime in WebAssembly that you can bring with your app. It's small and compact. Then you just download normal .NET assemblies into the browser and execute them using that runtime. Okay. The same UI components, the Blazor components, in this case they're running in the browser itself. They handle UI events, they calculate the diff about what needs to be updated, but that's all happening in process in the browser client side. So I see our little slide here says Preview. That's right. So Blazor WebAssembly is in Preview. Blazor WebAssembly is in Preview. Blazor Server however, is ready to go for production. Go ahead and click to the next slide. Yeah. When do I want to use which one here? Server versus WebAssembly. So Blazor Server shipped with .NET Core 3.0. Okay. LTS. Also shipped with 3.1 LTS. LTS is a long-term support release. So Blazor Server is ready for production use today. You can put it in your websites, put it out in production, it's fully supported with a long-term support lifecycle. Blazor WebAssembly still in Preview, isn't quite done yet, but we're working real hard on it. We expect to have that finished up in just a few months later this year. How do you pick between the two? Well, there's some trade-offs with Blazor Server. The benefits there is, well, first of all, it's production ready. Yeah. You can actually use it right now. Your code is also running on a full .NET Core runtime. So it's super fast on the server, and it treats the client as basically a thin client. It has less demands on what the browser or the client device needs to do. So for example, if you want to support older browsers like IE11, you can do that with a Blazor Server application because there's no requirement to support WebAssembly. Blazor WebAssembly on the other hand, gives you that option of pushing an offloading load from your server onto the client because it's a true client-side application. It can support things like offline scenarios. That's still in preview, so it's not ready for use today, but it will open up some really cool scenarios in the future. Oh my gosh. I'm so pumped. Now, regardless of which model you pick though, don't get too hung up on picking one versus the other because the component model is the same. You write your components once, and then you can use them in either hosting model. So you could start out, for example, with a Blazor Server app. If you want to switch to Blazor WebAssembly in the future, that's pretty trivial to do. Maybe when it goes to production, we can switch our components over. If that's what you wanted it? You can use it everywhere. Oh my gosh. I'm so pumped. Shall we get started? Let's get started. Okay. Let's do some Blazor. I know you can get started by going to blazor.net, so we have a really simple URL to remember, just blazor.net and it'll take you to our main Blazor landing page and we can go to this get started documentation. This will walk you through everything that you need to do to get started with Blazor, all the stuff you need to install. If you're on a Mac, like I see that you are, there's a tab there for Visual Studio for Mac that has all the steps for getting Visual Studio for Mac set up with Blazor. So it's already installed.net core 3.1, and actually, since you're here, I won't read this. I'll just launch Visual Studio and you can walk me through it. Since you've already done it, you've already installed Visual Studio for Mac. You have.net core 3.1 on your machine, which comes with Visual Studio for Mac. So you're all ready to actually go with Blazor development right now. All right. So since I got 3.1 installed, I already have a Blazor server template, and if I didn't see that there, I could actually just find that in just the regular app templates, Blazor server app. Under.net core, that's right. Cool. Okay. See, it's already targeting 3.1. We have a little authentication tab. So in the latest preview of Visual Studio for Mac, they now have support for the authentication options for Blazor server. So you can create Blazor server apps that support Auth using ASP.net core identity. Cool. All right. I'll go ahead and initialize one. I called it Blazor app 7. That's a wonderful name for a Blazor application. Seven is just my favorite number. It has nothing to do with the precise number of times we practice this. Nothing at all. Just lucky. It's a lucky number. It is. So this will create you a new Blazor server application. It's all ready to go. A Blazor server app is just an ASP.net core application with a couple of additional things wired up to support Blazor server. Why don't we go ahead and just run it so we can see what the application looks like. Yeah. Sounds good. So the Visual Studio can now build your application, get it running, you can debug, you have full support for Blazor development within Visual Studio for Mac. Once this gets building and actually running, we should see a sort of standard single-page app style UI. Give it a second. It's coming. Slowly. I believe. My Visual Studio might have fallen asleep as we were talking. Cool. We'll blame that on the browser. Yeah. So you can tab around, you have different tabs for different pages. This is all being handled through client-side routing. On the home page, you have some simple static markup, nothing too fancy going on there. On the counter page though, you have a button that you can click, and as you click, the count goes up. There's no page refresh happening here. The DOM is just getting fluidly updated. Normally, that would require some JavaScript to do, but that's all happening using C-Sharpen.net. Neat. Not to see how that's working. Yeah, and then this fetch data page is basically a dynamically generated table of weather forecast data. Ooh. So let's take a look at that counter page. So that's implemented in this counter.razor file. And you can see it's pretty simple. It's mostly just a standard HTML markup. At the top, it says that this is a routable component. So app page says that we would browse to slash counter. We should end up here. So if you go to the browser, you should see in the URL at the counter tab. Yep, slash counter. That's where we're at. And then you have some normal HTML markup. We've got a button that we can click, and there's that on click attribute. Normally, that standard HTML on click attribute would have some JavaScript in it, but here we're using a razor syntax, a little at sign to say, no, no, no. I would like to use some C-Sharpen. We've got C-Sharpen code here. Go down to that. And it's pointing to your C-Sharpen method increment count. That's incrementing the current count field, which then gets re-rendered on the page. Now to show that that really is running C-Sharpen code when every time we click that button, set that break point. Let's see if we can hit a break point. So that was on my counter page. And there we go. Got it. We're in our C-Sharpen method. Neat. Writing client-side web UI using Blazor. So let's see. What else is going on here? Well, the nice thing about these components, like all these .razor files, they get turned into normal .NET classes as part of the build. And now you can reuse them. Like if you wanted to have another counter component someplace in your app, you can do that by just adding that component wherever you'd like it to be. So for example, if we wanted to add a counter component to the home page, like let's say we wanted two counters. One on the counter tab, one on the home page. If you go back to the index.razor file, that's the home page for the application. Got it. OK, so here it just has markup. There's nothing really interesting going on. But let's start typing bracket counter, angle bracket counter on here. So yeah. And you can see you get awesome IntelliSense and Visual Studio for Mac. And now it's showing up purple. That's signaling to you that this is a component. Yeah. You know what, a blazer component. If we rerun the application on the home page now. Wait, is that purple or brown? I think it's purple. I might be a little bit colorblind. Purpley. .NET purple. Every once in a while, you learn new things about how you perceive the world. Yeah, maybe my. OK, so I added the counter component, and I'm going to go ahead and F5 again. Yeah. And so now when I go to the index, yeah, it has a completely new component apart of it. So it didn't need to copy in the counter code or anything. It's just inheriting that component. A reusable chunk of UI. You can click on it. It works just like the other one did. And if you go to the other counter page, you see it has an independent count that's separate from the counter on the home page. You can also pass data into components. Like components can have parameters to define a parameter on a component. Let's go to counter and make it configurable, parameterized how much it counts with each click. So to do that, you just add a property. And the property can be made a component parameter by attributing it with the parameter attribute. Gotcha. I have a little tip I want to show in here. Visual Studio for Mac does indeed have snippet. So if I just type prop and tab tab, it automatically loads in my property. Sweet. OK. Save some typing. What were you saying? So let's make it an int. Yeah, and let's call it increment amount, I think would be good. And let's default the value of that property to just one. Yeah, give it the parameter attribute, too. That's cool. So that's what's really going to make this a parameter for the component that we can pass in. So by default, it'll be one. And now in the increment count method, instead of incrementing by one each time, doing a standard increment, we'll increment by increment amount. So current count plus increment amount. Perfect. You get lovely IntelliSense for your C-sharp code inside your razor files. I like that, getting over my local variables. Now go back to the index page and let's use that parameter. Let's pass in an argument. So if we go to index, now just add some space after the R and then you can see increment amount shows up. Wow. The way you set parameters in Blazor is just using standard attribute syntax. And now the counter on the home page should increment by 10, whereas the one on the counter tab should just default to the standard increment amount of one. I just kind of chose 10. I hope that's a good number. That is a great number. 10 times better than it was before. Good. So I should get a build, this should spin up. And we should see. OK, let's check this. Yeah, so now it's incrementing by increments of 10, whereas the counter on the counter tab should still be doing by one. Because we didn't pass any parameter value. Yeah, so it's still going by one. Now how is this working? Like we said, this was all based on that magic real-time pipe. We can actually see that happening if you inspect the browser depth tools. Let's look at the network. And if you do a full reload, so we can see all the stuff that's being downloaded, like holding the shift key or something. There we go. So you can see that this app's pretty thin. It's not downloading very much stuff. It's just a little over 400 kilobytes of download. And all the magic is really happening in that first request, that underscore blazer web socket request. Yeah, you see, when you look at the messages, you can see there's all these binary messages flying on that web socket connection. Yeah, it's updating as they speak. If you clear it, let's clear them all out. And then go click on the button on the, sorry, yeah. Here, I'll clear again and use the keyboard shortcut. There's lots of buttons to click on. Try the, yeah, that'll work. And then click clear and click on click me. Click me button, that's insane. So see, every time you click, every time you click, we send the UI event to the server, your counter component gets the message, it re-renders itself and then the DOM updates gets sent back to the client. That's what's happening here. That's how this app is working. This is a blazer server-based app. Cool, so that's counter. Now, I know, if you go back to the code real quick on the counter.razor file, some people really, like you noticed that there was that at code block at the bottom, yeah, right there. So at code, that's basically a chunk of code that's gonna get added to the generated class for this counter.razor file. It's like a bunch of class members. And some people really like that that code lives in the same file, cause all your UI codes in one place. Other people would prefer to have that in like a normal C-sharp file, like in a code behind file. Which is totally cool, you can do that in blazer as well. What you can do is add a, let's add a C-sharp file to the pages directory. Let's call it counter.razor.cs. That's sort of the standard naming convention for a code behind file. Look good? Yeah, that looks good. What? It automatically put it underneath my counter got razor. I put a whole bunch of licensing information. Sorry, I was messing with my header demo for later today for the productivity talk. I'd elit that. We won't add it. You don't get to see this yet. You have to wait till this afternoon and we'll talk about how to put headers at the top of new classes. And we don't automatically license like all your C-sharp files that get added. No, no, no. We just did it for math. That would be bananas. I specifically chose the MIT license. Cool. Well, we have a counter class now. Now this matches the name of the class that will be generated from counter.razor. So let's make it a partial class. So can this? Oh, okay. Yeah, grab that code. Go ahead and grab that. That's fine. Go ahead and copy that out of there. And we're going to move it into here. We don't need the constructor so we can just copy over the constructor. But make the class a partial class so it will be combined with the generated class for the component. And then you probably need to resolve some namespaces. Right. And I can do that with alt enter. So that opens up the little light bulb that I get so I can automatically add usings. Beautiful. Love it. I guess all the normal C-sharp productivity enhancements and features now are available to you in this C-sharp file. Yeah, and I'm getting another little suggestion. So this actually might have annoyed some people when I did this originally. I didn't use a compound assignment. It was all part of my plan. And BS for math just takes care of that. Yeah, so BS for math gave me the suggestion that I can simplify that. That does look better. Yeah, cool. So this should be the same as what you had before. Like there's no difference in the code. It's just that we've refactored the code. Should I run it to prove it? Yeah, go ahead and run it to make sure it's still working. That's pretty nice, like the C-sharp. So I got a lot of nice features and languages. Oh my gosh. All of the little things. That's what I work on. That's nice C-sharp little things. Beautiful. Refactorings, cofixes, productivity. That looks like it was before. So you should still have like increment by 10. All that stuff, yeah. Increments by 10, looks good. What other C-sharp stuff can you do in VS for Mac? Does it support all the Visual Studio? It does. So right now we actually share the same editor. So basically everything that we've added actually latest in like Visual Studio and Windows 16.5 Preview 2, I believe is what we're on. All of those are actually already piped in to Visual Studio for Mac. Nice. I can demo those later today with Mikayla. There's a whole talk on that stuff. Yeah, there's like a shared editor. So it's all piped in. Okay. So like adding an overload? Like is that? Oh, yeah. So if I do Alt-Enter, our keyboard shortcut to open the little tooltips, I can- Override, I'm not saying. Override, sorry. I'm always getting my C-sharp terminology messed up. You can do something like initialize. The thing about this is you can see all of the component lifecycle events in this UI. Like the uninitialize on parameter set. These are all standard events in the lifecycle of a component. So yeah, if you wanted to like run some code when this counter component is first, after it's initialized, you would override oninitialize or oninitialize async if you have some async logic. I think the fetch data component actually does that. So this is the component that was generating that dynamic table of weather forecast data. And if you look at the bottom, all the way at the bottom, there's a, yeah, there. So you see oninitialize async. There's the example. I was distracted by how cool it was to have a C-sharp for each loop printing out your table. Razor. It's super cool. Okay. Sorry, continue. That's good. So yeah, there's oninitialize async. That's, when this component gets initialized, you see it's using that weather forecast service to get all the weather forecast data. Where's that forecast service coming from? If you scroll all the way back up to the top, there's this atinject directive. And what atinject is doing is it is a way to do dependency injection into your components. You can get services that you've configured. Here we have a weather forecast service that we're injecting into this particular component. And then below is just normal razor syntax like you were saying. It's mostly standard HTML markup, but intermingled with C-sharp logic. It's statement, yeah. If statements for each loops, like we're just looping over each weather forecast instance to generate the rows in that table. That's how that weather forecast table is being generated. Super cool. So we started sort of to get more into realistic scenarios. This was just the file new template. This is the basic stuff. Is there like a level two app that we can use and show off? Sure. So I've been working on a recipe app in Blazer. To like, you know, manage a list of recipes and do recipe ratings and those types of things. Why don't you pull that up? I think I found it. That's my repo. If you guys want to download and see my code. Like. Dan Ross 27. Okay, got it. Best for you recipe. Best for you recipes. All right. So let's see if I can open this up. Now I usually, I've been developing this on Windows actually on Visual Studio, but it opens great on Visual Studio for Mac, builds, runs, debugs, all those things just work as expected. Once this opens up, why don't we just go ahead and run it first just to see what the app is capable of? I'm going to wait till I load my workspace document. Perfect. And maybe restore my new get packages. That's probably important. I always kind of want to do that. Restore your new get packages before you build and run. You get that kids. It's okay. It's lifestyle choice. Okay. So I'll try to. It's saving. Might have gotten a weird state. While we're waiting for that, we can go ahead and look at the homepage at least. Let's open index.razor. So we can see a little bit what the, when we see the app, we'll have an idea of what the code looks like. This is the homepage for the application. And you can see at the top, it's mostly just a, there's a search box. And then a little bit of an if, if else then to see if the recipes have loaded. And once they've loaded, it's just generating an unordered list with the list item for each recipe that it loads from a recipe store. And again, we're using dependency injection to get a recipe store service and to initialize the list of recipes. So that's all that's doing. That search box at the top is a custom component for handling the searches. Why don't you scroll back up to the top and then we can look at that real quick. Yeah. So you can see that on the search box, we're passing in normal HTML attributes to like specify a placeholder. But we're also able to specify a delegate for when a search has occurred so that we can hook into that and actually then run the query against our store. So it looks like the app's now up and running. Yeah. So here's that homepage that actually rendered. Oh my gosh, beautiful. Nice, nice images. You must have got some help. You can- A little bit. A little bit, yeah. You need a beautiful app. Design is not my forte. You can click on recipes. You can see details about the recipes. Yeah, I can. Some basic functionality. We've got a little search bar. Search for chocolate stuff. Yeah, now notice that as you type, the search is updating. Like you're not hitting enter as you're typing. It's just looking at the current state of the search query and running a search. But it's not doing it on every single keystroke. It's like a little, there's a little pause that it waits to see if you're done typing and then it does a search. And that's nice because it's throttling all the searches to your database. You're not just hammering the database with every single keystroke. So it's interesting to see how that's implemented in Blazor. If we look at the search box component, that's where all that logic is encapsulated. So search box dot razor up there at the top. Now, this is that component just implements the search text box. And it's handling all that debouncing logic where every time you search, it will wait a little bit until you do your done typing. So mostly you can see that this is just an input. Like scroll scroll to see the markup at the top. It's an input. And that- That's not about timers. Yeah, and it's bringing in the timer's namespace. The attributes, attributes attribute there, what that's doing is allowing you to grab any additional attributes that are passed on the component and sort of splatting them wherever you want them to be. That's how that placeholder attribute is getting onto the input. And then that at bind is binding the value of the input to the search query property. So as you type, Blazor will see that the text has changed and then set that text onto the search query property, which I think you have below. Yeah, right there. And it's actually even specified as a parameter. So if you wanna pass it in, you can do that. And we know that it's gonna do that on every single keystroke because after at bind, back at the top at the end of the input, all the way to the end, see that at bind colon event, that's specifying which event we want to use for the bind. Like by default, it will do it on change. Here we're saying, no, no, no, I want it on every single input. Every time you type, please update the value of the search query property. And then now let's look at search query because that's where the little bit of cleverness is happening. Search query, when it's set, like when the value gets bound, it just starts a normal.net timer. And this is just like you saw up above, system timers or whatever the namespace is. It's a normal.net timer from the base class library where it will stop the timer if it's already been started and start a new one. And if that timer completes, then you know there was a pause without any keystrokes hit. And that's when it'll actually call back into the search query changed event callback that was passed in. So that's- You've got that debounce parameter there that 300 milliseconds? That's the amount of time we wanna wait. Then you can see in an onInitialize, there's that component lifecycle event again. That's where we're newing up the timer, setting up the debounce timeframe and wiring up the event handler for when the timer actually completes. So all the event handler does is call into your delegate that you passed in and then you get your search results. That's debouncing logic in, you know, 50 some odd lines of code all done in C sharp. No JavaScript required. That's great. So should we go back to slides? Are we short on time? I think. I forgot what time we were supposed to- We wanna make one change. Oh, we got five minutes. Oh, go ahead. Let's make an edit to this app. Let's make a change to this app. Okay. So if you go back to the app- What do we wanna do? Yeah. Let's go back to the app and look at the- Yeah, reload. Oh, right. I stopped the button. So click on the recipe that brings you to a recipe details page. Okay. And most of that's just markup and there's even a form where you can do star ratings. But there's also these tags and currently if you click on a tag, they are links, but they don't go anywhere. Oh. Like they don't do anything. So what we wanna do, it is going to a new URL. It's going to slash tag and then the name of the tag that you clicked on. Let's wire that up so that we actually end up on the search page but with the correct list of recipes. Okay. So go back to index.razor. What we wanna do is grab that value out of the URI. So in order to do that, we're gonna add another route. So add another app page directive and make it slash tag and then slash, now that's in curly braces because this is the value we wanna grab out and we'll call the value that we're gonna grab out tag. Okay. Now to get that value, we're gonna bind it as a parameter on this component. So add a new parameter. Remember we added a property before to create a parameter. Do in the code block, let's create a new property. So prop, tab, tab. In the code block. Oh, regular recipes. All right. Anywhere, it doesn't matter where. Prop, tab, thank you. Love it. Let's make a tag string and call it tag. Tag. Oops. Tab again. There you go. Okay. So and then put the parameter attribute on it. So now what the Blazor will do is it will take the value from the route and set it on that property. So now we can just pass it in to the. Can you tap the get recipes? Yeah. All right. If it's not specified yet then we probably just will pass empty. That will give us all the recipes when the tag is initialized. One more thing is up above in the search box. Let's make sure we populate the search box with the tag if there's one there. So set the search query parameter. Did I? Get a little space in there. There you go. There you go. There you go. You get a lovely IntelliSense. I wanted it to just fill all that out for me. Do at sign and tag. Oh, so we're actually getting into the C sharp property with that at sign. Okay, cool. That's all you need to do. So now it should populate the tag. So go ahead and run it. Okay. Restart it. And that should populate the search box with the tag as you click on tags. That will filter the search. So just that tag. Whenever you click on a tag leak on the page and it should be just that easy. Okay, so click on a recipe. Let's go down to the tags. Let's, I don't know, fruit. There's only one fruit. Got it. But that works and it populated the search box. It populated. You just added a feature to my app. Thank you so much. Hooray, you're welcome. Now let's hop back to slides real quick. Sure. So that was getting started with Blazer and some Blazer in action. We know the number one question on a lot of people's minds if we have time for Q&A and stuff is what is next for Blazer WebAssembly? When we get it, when will it be out of preview? Yeah, so this was all Blazer server work that we were doing with Visual Studio for Mac. Visual Studio for Mac fully supports Blazer server, which is great. Blazer WebAssembly is still in preview. It hasn't shipped yet. It is the focus of the Blazer team right now and we are planning to release it in May of this year as a supported release. And that will include full support in Visual Studio for Mac. The initial release of Blazer WebAssembly will be based on .NET Core 3.1. In fact, we plan to add the template in an update to the .NET Core 3.1 SDK. It will be a current release, not an LTS release. So it's not gonna inherit the LTS status of the rest of .NET Core 3.1. It is the first release of Blazer WebAssembly. We wanna give it a little bake time before we bless it as an LTS release. To try and make that clear, we're gonna update the versions of the packages to be 3.2. We've actually already started doing that. So the latest preview is our version does 3.2. After May, Blazer WebAssembly will become a part of .NET 5 and will then be just part of the normal .NET update release cycle. So I just need to remember to keep clicking yes on that update prompt. Keep, keep, keep updating and look in May for the release version of Blazer WebAssembly. Got it. So in summary, we talked a little bit about being productive in Blazer on VS for Mac. Blazer server is what we showed today. It is in production. You can go and use it with .NET Core 3.1 and get excited for May, 2020. For Blazer WebAssembly. For Blazer WebAssembly. So Q&A time? Questions? Are there questions? That's exactly it. I'm gonna actually start with a statement. Somebody said, I want Dan Roth's Visor Studio T-shirt. You can be an Uber geek too. I know, but you know what? We have some exciting t-shirts for this event and we'll be giving them out as part of our party. So make sure you stick around until the end of the day. So not just that, but more. And we actually have some questions as well. So the first one is, hey, VS for Mac, is there any way I can explore on Blazer WebAssembly in Visor Studio Mac? That we were just talking about that. You can actually open a Blazer WebAssembly app in VS for Mac today. You'll need to use the AceNet Core hosted version of the template. The standalone version of the Blazer WebAssembly template isn't working just yet in VS for Mac, but it will by the time we ship Blazer WebAssembly in the May timeframe. You don't have the ability to create Blazer WebAssembly apps from VS for Mac just yet, but that is coming as well. So you can create apps from the command line as long as they're hosted in an AceNet Core app and run and develop your components and all that. The rest of the functionality will be coming later as we get closer to the May release. That's great. Well, there you have it. And next one is, let me just close this one down. Is there a performance benefit using Blazer Server over Blazer WebAssembly? Yeah, so Blazer Server runs on a full .NET Core runtime. Your components are running on the server. So you get all the performance benefits of .NET Core, which is honestly one of the fastest stacks on the planet. It really treats the client machine also as a thin client. So it has very little requirements on the client side of the application. Blazer WebAssembly runs on an IL interpreter-based runtime today. So if you have components that are doing really computationally intensive stuff, it can drag a little bit when you're running that type of code in the browser. You might want to offload that to a web API, somehow onto your server so you're running on the full .NET Core runtime. Perfect. I think we have time for just one more question. So the question is, is there a benefit using Blazer over Angular or React or some other spa? Well, yeah, I mean, because you get to use C-Sharp. Yeah, no context with scene. You get all that syntactic goodness. All the productivity features in Visual Studio. Yeah, it's a full stack solution for web app development with .NET and C-Sharp. I think also there's just a lot of really nice simplicity that comes from the Blazer programming model and tooling. Like it's really easy to get started, file a new project, and you're up and running in less than five minutes. So that can be really nice. That said, if you love Angular and React and View and you want to continue to use those for your front-end development, you can absolutely still do that and still use .NET Core for your back-end APIs, GRPC services, signal or hubs, and so forth. Great. Well, thank you very much for your time. It was fantastic to hear about all the Blazer coolness out there. And I'm looking forward to the 2020 build announcements that we're probably going to have.