 Hello, everyone. Nice to see you. It's great to meet some of you so far, and it's always a pleasure to see your happy shining faces. My name is Steve, and I am a developer. I work at Microsoft on the.NET team, and I would class myself as a big believer in WebAssembly. I've been working with this and focusing on it professionally for about five years now, and I am pretty convinced that the majority of the potential of this technology still lies ahead of it, and the people in this room are probably going to be some of the key people to unlock that. Now, speaking of the people in the room and those people watching the live stream, I know that many of you are technology creators or influencers, innovators, perhaps you run open source projects, maybe you've got a startup in this space or you would consider doing that in the future, and you probably want your technology to reach and appeal to a wide audience, the widest audience you can, you probably want to go beyond just the Rust community and the assembly script developers, you probably want to make your stuff appeal to the really big technology communities. So I'm talking things like Java, Python, .NET, JavaScript, you probably want something that all those people are going to be into. Well, that's kind of what this talk is about here, because in the .NET world we've been doing WebAssembly for a few years now, and so we've built up quite a bit of experience of what it's like to work with mainstream developers and these technologies. And that's what we'll talk about. I'll show you a bunch of examples of stuff we have done and will do, but just before we get to that, I know that not everyone here will have used .NET, so I do need to just spend the first one or two minutes just giving you a quick recap of what .NET is, otherwise this might not make sense to everyone. So .NET is a general software platform from Microsoft, which consists of a bunch of different pieces. One of those pieces is the languages. You will have heard of C-sharp, I'm sure. You might have heard of F-sharp. There's various other languages that all compile to this common bytecode format for .NET, which runs inside the .NET runtime, and that brings additional services like garbage collection, just-in-time compilation, and so on. And if you are a Java developer, this might look like a very familiar arrangement, because it's pretty much the same kind of managed code structure. And then there are various frameworks built on top of all this. So, for example, there's ASP.NET Core, which is a general web technology. There's Blazor, which is for web UI. There's Maui, which is for native UI, and various other things, which you don't need to know about. But they're all there, and they solve different people's problems. And then tying all this together is a single package ecosystem called NuGet. Now, you might have heard of something called .NET Core, but what is .NET Core, and how does that fit into this? Well, in about 2014, 2015, we completely reinvented all of this. We rewrote it almost from scratch. That's when .NET became fully cross-platform and open source, and it was such a big change that we gave it a new name, .NET Core, which was nice. And then after a few years, we thought, hang on a minute, what were we thinking? That's a terrible name. Like, .NET was already a dubious name, and just adding a random word to it turns out doesn't actually help. So we thought, OK, let's just scratch that out. Pretend it didn't happen. We'll go back to calling it .NET again. So, you know, we're great at naming in Microsoft. We've gone back to .NET now. It's nice and simple, except if you use ASP.NET Core, because that is keeping the word core for reasons that nobody knows or will talk about. OK. So that's dubious naming, but a good technology behind that. So speaking of the technology, there's still some prevalent myths about .NET. I just need to dispel a few myths. So, yes, modern .NET really is open source. It's MIT licensed. It has been for years, and it really is cross-platform. You can develop on Windows, Mac or Linux, and deploy to any platform that you want to. And quite a lot of people do. So according to the Stack Overflow Survey last year, around three in 10 professional developers globally are using .NET. So it's a lot of people. Now, I am not trying to sell .NET to you here. I don't care at all whether you like it or not. I'm simply trying to make the case that this is a large developer community and that Microsoft does a lot of work to make the performance and reliability and simplicity good. Because we're interested in technologies that will appeal to wide audience. But mainly, we want to talk about .NET and WebAssembly. So let's think about that for a minute. And you can kind of split this space into two parts. You can think about the stuff that we've already done up until now, and then the stuff that we might do in the future. Now, the main thing that we've done up until now is this thing called Blazor WebAssembly. So Blazor is a UI framework for .NET, and it was originally designed to run in the browser on WebAssembly. We started the first prototype in about 2017, so that's just when WebAssembly came on the scene, and it's been supported in production since 2020. And it allows you to do the sort of thing that you would do with another front-end framework, like View or React or Angular, but with .NET inside a browser. And it's going very well. It's a popular part of .NET. In fact, it's one of the fastest growing parts of .NET, and it has been for some years. And I'm going to show you more about how that works, what the developer experience is like, and what we've learned in a minute. But first, let me just give you an example so that we all know what we're talking about here. So I'm going to show you a quick sample application, and I'll show you the code behind it in a minute. So this sample represents a typical kind of business application, because you know, most people want to build business applications, and this is C-sharp.NET compiled to WebAssembly, well, compiled to run on WebAssembly. Talk about that in a minute, running inside the browser, and it's talking to a .NET back-end server as well. It happens to be communicating with GRPC, GRPC Web in this case, and it's getting some data from a back-end server, and that's the sort of thing that people want to do. And if I go over onto this inventory screen, you'll see we've got a nice big grid, which makes sense, because most business applications are built out of big grids. And this really is a big grid. We've got 100,000 items in there, and the performance is really nice. I can just scroll to any point in that entire 100,000 items, and it just comes up instantly. And that is possible because we've got all the data inside the client here. So we've not only got .NET running on WebAssembly, we've also got SQLite compiled to WebAssembly running inside the browser too, and they can communicate with each other instantly, which means that we get very fast performance. So as I start typing, you see queries are resolving on every keystroke. Sorting is instant. Filtering is super fast. We've got 60 frames per second of filtering as I do that, and that's all very nice. So people are feeling good about that. They're being nice and productive. Let me show you a little bit of some code that's going on behind there. So I've got a few different things. I'm certainly not going to go through every line of this, because there's a lot in there. So I've got this central server project. That's ASP.NET Core on the back end. I would say most people who use Blazor WebAssembly probably are using .NET on the server as well as on the client. You don't have to, but it's probably the most productive arrangement, this full stack, because if you've got the same technology on both ends of the wire, then, well, you've only got to think about one thing, but also it means that we can share code, we can share our domain model types, and we can pass data between server and client without any friction. So people generally tend to do that. Then I've also got this manufacturing hub project here. That's the actual Blazor WebAssembly application, and there are two main types of files in this project. So the first type is C-sharp, and this is my program CS. This is where my application starts up, and it configures all the services and stuff in there. So general C-sharp is going to work. But also the other main type of file in these projects are these RAZR files. RAZR is our syntax for being able to have markup as well as C-sharp, and that's how we're rendering a web UI. Now, the actual application architecture of a Blazor application is basically the same as all other front-end frameworks. So you know things like View and Svelte and React. They've basically all ended up with the same kind of component-oriented architecture, and Blazor is no exception. It's pretty much the same kind of way of structuring an application. And then in terms of actually running this in a browser, you might think that we're compiling C-sharp to WebAssembly. Well, we can do that, but that's not actually what we do by default. It's not what we do in development. In development, we're using an interpreter where we compile the .NET to regular .NET assemblies and then run them on a runtime that itself is compiled to WebAssembly. And to show you that, I'll go into my browser network tab, and we'll have a look for DLLs. And you'll see that I've got a bunch of DLLs in there. In fact, I've got an enormous number of DLLs, loads of them. And that is because this is a development build where we optimize for compile speed. Developer experience is key here, so we're not doing any code stripping in development. We just dump everything in there, and these are normal DLLs produced by the C-sharp compiler, which is very fast. It can build something like this in a second easily. And then to actually execute them, we've got the .NET runtime compiled to WebAssembly. And in a production build, that file can be as small as about 300 kilobytes. We've done a lot of work to optimize that. Now there is another execution mode for Blazor WebAssembly, which is ahead-of-time compilation, where we do compile all the C-sharp through to WebAssembly by code. And that allows the application to run a lot faster, but at the cost that the build time is also quite a bit longer. So we don't want to do that while people are actually developing. Okay, so what's the product goals for this sort of thing? What are we trying to achieve? Personally, a goal that I've always had for this right from the very beginning is to help front-end web development move beyond just JavaScript. I like JavaScript. It's a good language. I built probably the first half of my career on it. But the software world is much broader than that. There are many different languages and platforms and different approaches to programming, and I would love it if front-end development could make use of all those. And then the other reason is, of course, to make .NET developers productive. It's not just about bringing the C-sharp language into the browser. It's about bringing the full .NET experience. And that includes things like the C-sharp language, but it also involves all of the tooling. When you're working with a mass market developer audience, they know what tools they like, and they want to keep using them, and they're not going to accept some new tools that you make up. So we need to make all the existing .NET tooling, the debugger, trimming system, hot reload, they all have to work. But also critically, the entire package ecosystem, people expect that it can use any package they want, and they won't be happy if you tell them they can't. We couldn't call this .NET if you couldn't use the whole .NET package ecosystem, just like you couldn't call something Go or Python if it didn't support the corresponding package ecosystem for that. And the net result is that people get to build these full stack applications with .NET on both sides of the wire, and I think that the same approach could work for other technologies too. You could easily imagine having Python on both ends of the wire for web development, and that would be productive. OK, so I've been really focused on developer experience so far, so let's experience that ourselves. Let's have our own little developer experience right now, shall we? Let's imagine that we find some bug in this application. I'm going to just open something like this rocket motor here, and you can see that at the bottom there, it's got this little cost calculator, and as I change it, it tells me the price for different numbers of units. But let's say someone reports a bug, and they say, hey, did you know you can have a negative number of items with a negative price? That's kind of absurd, isn't it? And you think, all right, fine, yeah, I'm going to fix that. Most developers at this point are going to start reaching for a debugger. But can we debug C-sharp when it's running inside a browser on WebAssembly? Yes, we can. That's important. It wouldn't be much of a developer experience otherwise. So to get into the debugger, I'm going to press a magic hockey, Shift Alt D, and when I do that, a browser DevTools window is going to appear. And this is the normal Chromium DevTools, which you all seen before, you all know and love it. It's got JavaScript and CSS and stuff. But because this is Blazor WebAssembly, it's also got all of my .NET application files. For example, I've got my C-sharp sources here in the browser. I've also got all of these different razor files. And I happen to know that this stock label pop-up thing here is rendered by this part details razor file. And I also look through it and I see, okay, this is where we get the cost statement, the formatted cost. So I'm going to drop a breakpoint right there in the middle of my razor file. And then if I go back over here and change this number, we will hit our breakpoint inside the browser. And I can just start stepping through the evaluation of my UI and right into the C-sharp code that is behind there. And we can see, okay, so here's the bug. It's fairly clear that there's a bug here. It does nothing about the fact that there might be a negative price. So should we fix that then? Let's go into our code editor. Let's just reorganize the screen a little bit. I'm going to want this and this. So there we go. It's kind of difficult to see when you've got such a small font, such a big font. But remember, we've just seen that there's a file called part cs, which contains this code here. And I want to fix it. So I'm going to say if quantity is less than one, I'm going to return not applicable. Okay, and then I hit save. And when I do hit save, what we should see in the browser is it immediately just changes to say not applicable. So this is the hot reload system. It's kind of standard in the JavaScript world, but it's not so standard when you talk about running stuff in WebAssembly. We had to do quite a bit of work to enable that. But now, when I've got a negative value, it'll say not applicable and for positive values, it'll give us the right numbers. So that's pretty nice. We've had a nice little developer experience. We've been able to use standard tools and do all the stuff that we expect. So that's kind of where we are with Blazor WebAssembly in the browser. Let's think about where we might go in the future. Now, there is, of course, a lot of excitement and momentum in the industry right now about WebAssembly on the server. And so we're thinking about what we could do to bring .NET to this new Wazi ecosystem. And there's perhaps two main reasons for that, or there's two benefits on both sides of this. So for the Wazi world, for the ecosystem that you're all developing, the benefit of us bringing .NET to that is that we bring a large audience of developers who are going to want to use your tools and your services, your hosting systems, and hopefully give you a lot more influence over developers' lives. And then for the .NET developers, it's beneficial because it brings them to the cutting edge or it keeps them on the cutting edge of where the industry is hopefully moving. Now, you might think that .NET on WebAssembly is already a solved problem, because I just was doing it right there in the browser. It was working. So we can just go home, right? But no, the way that we compile .NET to, or run .NET on WebAssembly in a browser is not suitable for Wazi environments because the current technology is built on M-scripten, which is designed for producing browser builds of stuff. And importantly, M-scripten works by making calls into JavaScript. All of the system APIs are mapped into JavaScript APIs, which is no good in a Wazi environment because there's no JavaScript in a Wazi environment. So we've started looking at a new experimental way of building .NET to running WebAssembly based on the Wazi SDK. And when you build something with that, it's much simpler. You just get a single file that comes out of it, and it does not rely on JavaScript. Everything is mapped into the Wazi system interface functions. So let me show you our new experimental SDK and I'm going to go over to a console here. I've got an empty directory, and this is in Linux, but it would be exactly the same if I was in Windows or Mac, so you don't really need to worry about the operating system. And we'll start by doing the simplest thing we can. And in .NET, the simplest thing probably is a console application. So I've created one of those. And in case you don't know what files are in a .NET console application, I'll open up an editor. And when we get in there, we should see that there are two files in there. We've got the csproj, which configures the compilation. We don't need to care about that. And then we've got program cs, which is just going to print hello world. So let's run that .NET run, and that will compile the application, restore its dependencies and stuff, and print out hello world. Very good. Let's just change it to display a little bit more info. So I'm going to display the current time in UTC and the current OS architecture. And I can go and do a .NET build, because you can build separately from run if you want to. You don't have to. Then when I do a .NET run, you'll see that it tells me the time now and the architecture of my laptop CPU is x64. That's great. But this is not WebAssembly yet. This is just normal .NET. How can we make this into a wazzy compliant WebAssembly binary? Well, we can do so by adding this new experimental SDK called wazzy SDK. And when I've done that, the next time I do a build, we should see some slightly different stuff starts happening. So it's still going to produce the normal .NET assembly for my application, but we won't actually be using that at runtime, because mainly what it's doing is it's preparing my application assembly and all the other dependencies to bundle them into a single standalone WebAssembly binary. And this is just using normal .NET tools, so our mass market developers will be happy to accept this. Works in VS as well. And now I can run this. So let's just copy that path. And then I can run it on any wazzy runtime environment. So I'm going to start with wasm time, which I'm sure many of you know about or even work on. And so if I run that file now, it will work exactly like you expect. We've got the time and the architecture is now wasm. And this is wazzy compliant. I can run it on a different wasm runtime if I want to, such as wasmail. And if you really need convincing that this is standard, I will dump all of the imports from my wasm file. And you'll see there's 23 imports. It's stuff to do with file system and clock and things like that. You don't need to read the list. But every single one of those is part of the wazzy snapshot preview one namespace. So it should run anyway. Excuse me. OK. So that's good. It's a good start. But so far it's a bit boring, right? Because we can only just log stuff to console. Can we build a more interesting application? Something that we would deploy to the cloud, something network enabled. So here's the little challenge that we're going to set for ourselves. One of my lockdown hobbies has been growing vegetables in a greenhouse, which is great. Yay. And when you get into doing this sort of thing, you tend to accumulate a bunch of sensors. Little IoT devices, they might be programmable. They collect information about temperature, humidity, soil moisture and stuff like that. And it's a bit tedious to go around looking at them all individually. I'd like to feed all that data into a central monitoring application, which can then present a UI to me on different devices. And I want the network traffic to be really compact. So I'm going to have them send GRPC messages into the application. And I want my UI to update in real time. So I want it to push updates out over web sockets. And the question is, can we do all this stuff with just standard wazie today? Is the ASPnet compilation model, is it going to work on WebAssembly? Is all the networking stuff going to work? Well, the answer is yes, obviously. Otherwise, I wouldn't have brought this up. It would have been a silly thing to do. So I'm going to show you how this might look. Over here, I've got my greenhouse monitor application, which is a standard ASPnet core application, which references the wazie SDK and another package, which tells ASPnet core that instead of using the native windows or Linux networking stack, it should use the new Sock Accept API, which is within wazie. And that should mean that all of the standard ASPnet stuff, such as GRPC and SignalR, which is our APIs on top of WebAssembly, they should all just work, which is very nice. I've got other configuration, like I've got this JSON endpoint for the UI, and I've got here my WebSocket thing. The UI in this case is actually built using Svelte. And you might wonder why I would do that, because I've just been bigging up Blazor. If Blazor's so good, why wouldn't I build the UI with that? Well, I could, and it would have been really nice and convenient for me, but the point is to show that all these technology pieces are independent. And just because you can use .NET for one thing, it doesn't mean that everything has to be .NET. So that's why I did it with Svelte. Also Svelte is quite nice. So, you know, that's okay. Let's start running this, shall we? I'm going to do a .NET build, and we should get a wazm binary out of that, because I've got the wazie SDK in there. So when that builds, we shall see. There we go, a greenhouse monitor.wazm has appeared. And I could run it using standard .NET tools, or just by pressing F5 if I was using Visual Studio, but to show you that there's nothing weird going on, I'm going to start it by calling wazm time directly, passing it a reference to my wazm module and telling it that it's allowed to listen on port 5000. And then I'll go to that in my browser, and we get our UI popping up, and it looks nice. You know, we can see that there's disturbingly high temperatures at one end of the greenhouse, but it's fine everywhere else. The temperature's been fluctuating and the automatic irrigation system seems to be working, so that's all good. But remember that we want to push stuff into this over GRPC and get the UI to update in real time with WebSockets. So I need some sensors. I don't actually have any sensors with me here, but I do have this little simulator that I wrote which is going to make the GRPC calls into the application, and we'll see what happens. With that, you'll see that the UI does start updating in real time because the SOC ACCEPT API in Wazi means that all the stuff we build on top of that is just going to start working, which is very nice. But what if something goes wrong? How could we diagnose what's going on inside our application? Can we debug stuff even when it's running inside wazm time? Well, wazm time does have some level of debugging support, at the level of LLDB or GDB, and it's not the sort of thing that .NET developers are going to accept. They want to use their normal debugging tools, but the good news is that the .NET runtime has its own debugger support inside it. So if we can attach a TCP listener to that debugger, then we can connect a normal debugger. So I am going to go back over here, and I'm going to restart my application this time, and I'm going to say, instead of just listening on port 5000, you can also listen on port 8001, and I've configured that to be the debugger port. I've also configured VS Code to use 8001 for the debugger, so I'm going to press the attach button right now, and it's kind of difficult to see what's going on because the screen is so small, but we can see that we've accepted a connection from the debugging client there, and then the application starts up. Now back over here in my browser, I can reload and everything's working and stuff, and then I can go and put a breakpoint somewhere. So let's go into here. This is the endpoint that receives the GRPC calls, and it loops through all the data that comes in a batch and puts it in the existing store, and then it sends out the notification of a web socket to all the clients. So let's see if we can hit that breakpoint. I'll go and start sending my sensor data into the application again, and when I do that, you'll see that we do, in fact, hit the breakpoint, and we've got an entirely normal .NET debugger working in the normal way for code that's running inside wasm time, and we can do all the normal stuff like hover to see variables, see the call stack, and all that sort of stuff, and that's working great. It even works with remote debugging, so I set up an instance of this in a cloud earlier, and I could connect a debugger to that in the normal way, and it worked great. So I want to give credit to one of the runtime engineers for making the debugger work here, so Taze on the runtime team did an amazing job. The first time that we tried to enable debugging for .NET inside the browser, it was like a six-month agonising effort, but when Taze looked at doing this on top of Wazzy, she was able to make it work in under about two days, and I think that goes to show how Wazzy is a more standard environment for running your WebAssembly code than the browser is. We can do a lot more stuff in a straightforward way. So we are running out of time now, or I've run out of time. I want to just leave you with a few final thoughts about things that I think we could do to grow the Wazzy ecosystem from where it is to reach a bigger market of developers. I've made this point a number of times. I think the developer experience is key. You need to have compile times under a second. You need to be able to use standard tools, standard debuggers, standard hot reload type features. People are not going to use any weird new tools that you ask them to use. I think there's a good opportunity when it comes to hosting this kind of thing. So I just built my Greenhouse app as a single Wazm file, and I would like to be able to just upload that file on its own to something that would host it in the cloud, but the industry doesn't seem to have got a feature like that just yet. But it's kind of an obvious thing to do. I'm sure many of you would be working on something like that. As for the various open source projects that are going on in the Wazzy world, some of them have got great samples, but a few of them I've noticed don't really have samples at all, or they've just got kind of like a Hello World sample, which doesn't really sell the technology, and I just really encourage you, if you've got any project in this space, to make sure you've got some samples that actually sell what's unique about your project, because people might not make sense of it. And then speaking of reaching a wide audience, you don't have to use Windows yourself, you don't have to like it, but most professional developers in the world are using Windows, and if you're not shipping Windows binaries for your project, then you are leaving a lot of potential users on the table. As for the Wazzy spec itself, I think we all know that there are some gaps in networking. It's been mentioned in the keynote. I know there's a session about this later in the afternoon. So it's great that we've got the Sock Accept API, that's what made it possible to just make ASP.NET Core work there, but there's still a missing piece in terms of outbound networking to be filled in there. We can't get every possible thing inside the Wazzy spec, so you know the new component model interface types are going to be key to making a wider range of things work on Wazzy, and it would be great if we as a community could get together and agree on what the high-level representations for stuff like HTTP, web sockets calls, database calls and stuff should look like. So that is all I've got time for, and I know that you'll be ready to go and get some coffee just now. So I'll just leave you with some links. If you want to try out any of the stuff that I've shown you there, you can go to these URLs and get the code and play with it yourself. But also I'll mention once again that the .NET Wazzy support is purely experimental at this stage. We've not got a commitment to ship that, but we really want feedback about that. So give it a go, try making your thing work with .NET and tell us how it goes, and we'll try to work with you to make sure everyone has a great experience. So there we go. Run out of time. Have a lovely rest of the day, and I look forward to chatting with many of you as we go.