 Coming up next, we have Dan Roth building amazing web apps with.NET Core. How are you doing, my friend? Pretty good. How are you doing? Good. All right, buddy. Take it away. All right. Hi, everyone. My name is Daniel Roth. I'm a Program Manager on the ASB.NET team, and I'm thrilled to be able to talk to you about building amazing web apps with.NET Core and Visual Studio 2019. Visual Studio 2019 comes with the latest version of.NET Core in the box, .NET Core 2.2 is loaded with a lot of great new features. We've done a lot of work on the templates to simplify them, clean them up. We've updated them to use Bootstrap 4. We also updated the Angular template to use Angular 6. Angular 7 will be coming in the next release. We did a lot of work on web API improvements. In particular, we provide now API analyzers and conventions that make it easy to generate complete swagger documents or open API specifications for your APIs. We added HTTP2 support to Kestrel, our cross-platform web server, and we also enabled in-process hosting support for IAS. We added a new health checks framework and also a new routing framework that we call endpoint routing. Now, let me go ahead and show you what it looks like to do web development with Visual Studio 2019 and .NET Core 2.2. All right. Let's go over here to Visual Studio. I'm going to create a new ASP.NET Core web application. Web application one sounds great. I'm going to put it in my demo folder. That looks good. Let's create that. Now, you'll notice at the top that ASP.NET Core 2.2 is already selected. I installed 2.2 of .NET Core. When I installed the web workload and the .NET Core workload as part of the Visual Studio 2019 installation. All right. Let's create a web application that looks great, create that, and this will go ahead and generate my project for me. All right. So we're going to wait for the package restore just to complete, and then we'll go ahead and build and run this and see what the template looks like. There it goes. All right there. So let's build and run it. While we're waiting for it to build and run, if we look at this template, hopefully you can see that it's a lot more lightweight. There's a lot fewer files in this template. We've done some work to try and slim it down, get rid of the stuff that you end up having to just delete whenever you start a new project, so you can get going faster with your new applications. Here's the application up and running now, just waiting for it to render. There it is. You can see now the new templates in ASP.NET Core 2.2. They're a lot cleaner, a lot simpler, a lot fresher looking, and this is all based on Bootstrap 4. If we go looking at the layout for this application, we should see Bootstrap 4 in here and there it is. Bootstrap 4 is wired up by default. This application is also using IS Express to host the application. Let's do something real quick. Let's go into the home page of the app. What I'm going to do, let's add a header here and let's print out the name of the current process that the app is running in. So, diagnostics process, get current process, and then the process name. There we go. So, let's just save that, and then I'll refresh the home page of the application. We should now see the process that the app is running in, and it's running in the IAS Express process. This is different than earlier versions of .NET Core and ASP.NET Core. In earlier versions, your app would run in a .NET Exe process, and then IAS would proxy requests to your application. I had a number of issues, it had a performance hit, and if anything went wrong with your .NET Exe process, then it was hard to diagnose what happened there. In starting in .NET Core 2.2, you can now host your ASP.NET Core apps directly in the IAS process, much better performance, much easier to debug and diagnose issues. So, that's great. All right. Let's go back to the app. Instead of running this app in IAS Express, let's now flip it to just be a standalone application, basically a console app hosting an ASP.NET Core application. Let's go ahead and run that, and now we should see the process should change, because we're no longer using IAS at all, so we would expect to be back to just running in a normal .NET Exe process, and we are. Great. Let's pop up the browser dev tools and look at the network trace as we refresh the application. There's all the files that are being downloaded. Notice that all these files by default are being downloaded over HTTP11. But in .NET Core 2.2, we've added support for HTTP2 to Kestrel. It's not on by default, you have to enable it, but it's really easy to do. Let's go ahead and do that. I've got a little code snippet here, and notepad, I'm just going to copy out. Let's grab that and then go back to the application. We'll stop it and then update our where we're building up the web host. So, let's go ahead and add a little bit of code here to configure Kestrel. I think we need a namespace. Yes, we do. Great. So, here you can see we're now enabling both HTTP1 and HTTP2 protocols. We're setting up HTPS so that we can do a negotiation with the browser to set up HTTP2. All right. Let's now rerun this application, running on Kestrel and see if we see any difference. Okay. We're back in the browser, still running on .NET. Let's look at the browser dev tools and refresh the application. Voila. Instead of HTTP1.1, you now see the protocol is HTTP2, which is short for HTTP2. This is great because it means we can take advantage of features like connection reuse, compressed headers, and all the optimizations that come with using the HTTP2 protocol. Cool. All right. What about web API development with .NET Core 2.2? Let's go ahead and close the browser and close this app, and let's open up a different project. I was working earlier on an API, my pets API, one of my favorite APIs to work on. This is an API intended to manage a list of pets. You can add pets, get the full list of pets and so forth. Simple crud operations. I already started a little bit here. I defined my model type. Here's my pet class. It has an ID and a name. Okay. Now I want to create an API controller based off of this model. So I'm going to use Visual Studio to help me do that. Let's add a new controller. All right. I'm going to create an API controller with actions using NAD Framework. So any framework will be used to actually store the pet data. Let's add that. For the model class, let's use pet. I already have a data context class that I'll just reuse, and for the controller class name, pets controller sounds great. So we'll go ahead and generate that. Now Visual Studio is going to take care of generating for me an entire API controller class with action methods that match all the standard crud actions like get, post, put, and delete. All the code for interacting with NAD Framework core is already done for me. So that's great. So I've got my API all set to go here. Now I've also already gone into this project and enabled Swagger generation or open API spec generation, which is the newer name. To do that, I use a great open-source community project called Swashbuckle. You can see here that I've got the Swashbuckle package added to this application already, swashbuckle.asp.core. Then if you go into startup, you can see that I've already wired it up, added the Swagger generation services, and then down below in my configure method, added the endpoints for generating the Swagger document and exposing the Swagger UI. So I should be able to now just run this application and see the default Swagger UI showing me my new API resource. Let's see if that works. Okay, great. We're at the Swagger UI and there's my Pets API. Awesome. And there's the default values API that just comes with the template. And if we look through this, we see all the things we expect. We can get the list of Pets, we can post new Pets, we can get individual Pets, delete them, and so forth. All right. But something doesn't look quite satisfactory, quite complete. Like if we look at, say, the post action in the responses section, it says that this thing basically always returns 200 okay. I'm pretty sure that's not the case. Like there might be errors, validation errors, or I'm pretty sure that normally in response to a post, you would say, well, a resource has been recreated. You've posted a new resource, 201 created. Here's the URL to the new resource. But that's not here. That's not missing. Is it in the code? Let's go look at our Pets controller again and look for the post action. Where is it? So there's put, yeah, here's post. Yeah, there's a, the returned value is a created at action, action results, which yeah, it says returns of 201. That's not documented in the Swagger document. Why is that? Well, there's only so much that libraries like Swashbuckle can do by just statically analyzing your APIs to figure out what the Swagger document should be, what the open API spec should say. Some things you have to tell Swashbuckle about using attributes and additional metadata. And this is one of those cases. Fortunately, in .NET Core 2.2, we give you an analyzer, an API analyzer. We can see it in the analyzer section. There it is. I've got it already added to this project. That will look at your API controller and tell you about all the places where you probably should add some additional metadata. In fact, you can see I'm already getting a green squiggle here for my post action with a potential fix up. If I go ahead and do the fix up, I get the attributes that I would expect saying that this action, by the way, returns of 201 created. So if we rerun this application now, hopefully our post action in the Swagger document should look a little bit more descriptive. Let's see if that's the case. Post and yes. All right, so now it says that it returns a 201, which is awesome. Also it has like a default response, which would be like in response to errors. And the nice thing here is that in ASP.NET Core 2.2, we added support for problem details, which is a standardized RFC, I think it's RFC 7807, there it is, for generating machine readable error responses. So that's already configured for you and set up for your API controller. Awesome, all right, so that looks good. But it would be kind of tedious to go through and add all these attributes to all my actions. Is there a better way? And of course the answer is yes. Instead of adding the attributes to each and every one of your actions, you can instead apply an API convention, which looks at the patterns that your methods match and applies metadata accordingly. And we give you a set of API conventions out of the box that match the API conventions that we generate in our scaffolded code. Until you apply those, you just use the API convention type attribute. There it is, there it was, there it is. And then the default API conventions that we provide are this default API conventions type, all right, cool. Let me save that. Actually, let me copy, comment that out. And then down below, if we look in the errors list, see the API analyzer is telling me about all the different action methods that are missing metadata about the response types. If I now uncomment the convention and again look at the error list, poof, they've all gone away. Everything has been fixed up for me. If I now run the application one more time, hopefully our Swagger document is much more descriptive. Let's see, so like the get that takes an ID, that you would expect to return 200 okay if it succeeded, yeah, 404 if the ID is not found, yeah, and then the default for errors and so forth. So great, now we have a really complete open API specification, all right. Cool, so that's, no, some of the new features that are in .NET Core 2.2 used within Visual Studio 2019. There are also a bunch of really great razor tooling improvements in Visual Studio 2019. Razor is the format that we use to generate HTML dynamically using a combination of HTML and C-sharp. Some of the improvements that we've added for Razor in Visual Studio 2019 is support for find all references, modern completions, and of course, live share. So let's go take a look at that. All right, back to Visual Studio 2019. Let's open up a different project. This is just an ASP.NET Core web app, but I've done a little bit more to this application. Here I wanted to generate some pages for managing products, so I've defined a product model type. It has an ID, a name, and a price, and then I went and scaffolded a bunch of Razor pages this time, some UI. Not an API controller, but some Razor pages. And the way I did that, I've already done it, but you can do it yourself too. Just add Razor page, and then Razor pages using entity framework. That's the one we want, add that, and then here I specified my product type for the model. I used my existing data context class, and then accepted all the defaults and clicked add. And after I did that, it went ahead and generated all of these nice Razor pages for me, which is great. Okay, so let's go ahead and run this app and let's see what it's got. So let's see, we should see our normal default template that we saw before with a nice bootstrap four-based clean UI, and then hopefully some pages for looking at products. So we've got a product tab up here that I added, and let's see, yeah, so we've got a list of products. So what do we got? We got a Razor, we've got a Blazer, is of course free, because it doesn't cost any code to write C-Sharp, and then AspNet, an AspNet, I assume that's some sort of net for catching poisonous snakes or something like that. You can almost hear the groans coming through the camera. Yeah, so we've got a list of products here. We can edit things, like if we wanted to go in here and actually make this ace net core and make that free as well, that looks good. So you can edit, you can delete, you can list the products, awesome. All right, well, let's go look at the Razor files and see what Visual Studio 2019 can do for us. Let's see, let's first look at find all references. Okay, so I'm looking at the product type, and you can see through code lens that it's telling me all the places where the product type is being used. And if I just look at the type, it shows up in all these C-Sharp files. These are all the code behind files for the Razor pages. That's the way Final References has always supported that, that's normal and expected. But what's really cool now is that if I look at one of the members for my product type, let's expand that a little bit so we can see it better, now we can see all the places where that member is being used in Razor files. Like here's the exact line where that property is being used. So find all references, now works with Razor, which is great. What else? So if let's go into the index page for this application, let's say we wanted to add a directive, like let's add an inject directive for like injecting a service into this page. I start typing at in, I course get completions over Razor Directives and all the C-Sharp stuff, but the nice thing is because we're in Visual Studio 2019, oh sorry let me, let me start that again, because we're in Visual Studio 2019, we are using the new modern completions infrastructure. So I can actually filter the completions by just the Razor Directives. You see that, it says Razor Directives on that button. And so I get just Razor Directives when I type that. Okay, let's go back to the at, at in and filter the Razor Directives and then we can complete it. Awesome, and then you can type your type here and so forth. So that's modern completions with Razor. Lastly, what if you need some help with your ASP.NET core project and you're working with Razor pages or views and you want to help from your buddy? Well, you can do that using LiveShare now. So I'm gonna go ahead and set up a LiveShare session for this Visual Studio instance. Okay, let's go ahead and do that. And this should then copy a URL to the clipboard. Yep, there it did. That I can now share with my buddy who can help me out. Now to emulate my buddy, I'm just gonna open up another Visual Studio 2019 instance and let's join that LiveShare session. All right, so we're just gonna do file, join LiveShare session and paste that URL in there and join it. Okay, while it's joining, I'm just gonna put these two Visual Studio instances side by side. All right, so we got nothing yet. Oh, it says that I joined the LiveShare session remotely from whatever part of the world. Okay, I can see some of the solution now showing up and there's the Razor file. And in fact, it even shows where my cursor is at. And now I can go ahead and start writing just normal Razor code. Like let me help you out there, Dan. You wanted to display the current time here, no problem. The current date is at date. And I get C-sharp completions in Razor, running in LiveShare.now. Yep, more C-sharp completions works awesome. Okay, now, and if I look at what's actually on disk in this guest Visual Studio instance and that's joined the LiveShare session, let's open the containing folder. You'll see that I've got like nothing here. Like this, all I've got is this, pretty much empty project and the files that I have, that have been shared with me so far that I've been editing. So I can write Razor code, get C-sharp completions for a remote ASP.NET Core project that's using Razor. That's pretty cool. So that's LiveShare. Let's go ahead and leave the session and shut that down. There we go. Okay, so there's some of your new Razor tooling features in Visual Studio 2019. All right, let's look to the future now when we can write client-side web applications using .NET instead of JavaScript. We have been working to make it possible for you to write reusable web UI components using C-sharp and Razor that can run directly in the browser and this is great because it enables you to share .NET code both on the server and on the client. You can have shared common logic. If you still want to call in JavaScript, you can do that too. You can call into existing JavaScript libraries, browser APIs using a JavaScript interop and for the initially, we will support two hosting models for these kinds of applications. We will support hosting these apps on a server where all of the UI interactions with the browser get handled over a SignalR connection or we will also support hosting these applications client-side in the browser on top of WebAssembly. Now what is WebAssembly? Well, WebAssembly is a relatively new open web standard that defines a byte code for the web and what this means is that if you have some code, as long as you can compile it to WebAssembly, it can now run in any browser at near native speed. This is awesome because it means now when you want to write client-side WebLogic, you can pretty much do it in whatever language or framework you want and of course, we want .NET to run great on WebAssembly. So we've been working on that for a while with this project that we call Blazor. Now what is Blazor? Well, Blazor, you can either run a Blazor app directly in the browser on WebAssembly, writing components, getting rich interactive UI or alternatively, you can write a Blazor app, same components and host it server-side in ASP.NET Core and handle all of the UI interactions with the browser over a SignalR connection. Now initially we will support the server-side hosting model for .NET Core 3.0. Later in the future, as soon as the WebAssembly.NET runtime is ready, we will ship support for client-side Blazor at some future point. Let me show you what it's like to do Blazor development with Visual Studio 2019. Okay, now these are actually, you know, brand new bits, hot off the press. I'm actually gonna shift over to developer build of Visual Studio with some updates and I'm using .NET Core 3.0 on this machine. Now initially what I've got here is a server-side Blazor application. It has a number of components that are implemented using these .Razor files. Let's just run the app so we can see what it looks like. All right, so compile and get it running. And this app actually starts up pretty fast and it has some nice functionality. You can click a counter and the counter goes up. You have a fetch data page that's retrieving some data and then rendering a table and then we have sort of a blank to-dos page. Now normally to get this type of behavior where you have interactivity where I click a button and the UI just updates without a page refresh, normally you'd have to do that using JavaScript but I didn't write any JavaScript to write this application. It was all implemented in C-Sharp and Razor. Here's the counter component. It has a page directive at the top to say that this is a routable component in some normal HTML markup. We use some Razor syntax to write out the current count. Then we have a button with an on click handler. Normally this would be JavaScript but we're using Razor syntax to say no, I wanna run some C-Sharp code here. Here's the method that we're gonna call every single time that button is clicked. Let's actually run this in the debugger. Get the app up and running again and then we'll go ahead and set a break point on the increment count method. All right, counter, we click the button and boom, we're hitting C-Sharp code. All right, so that's super cool. Let's go ahead and let this run through. How is this working? Well, if we look at the browser developer tools, let's refresh this. You can see this app is actually pretty lightweight. It's only got a few hundred kilobytes of downloaded payload but there is a web socket connection that gets set up with the server. Every time I click this button, we hit our break point again. Let's go ahead and uncheck that and let it flow through. You can see that bytes are flying along that web socket connection, talking to the server, running your components and then the UI updates get sent back. That is the server side Blazor model. Now in the future, we also want to support running those same components client side in the browser on WebAssembly. Let me show you that. So I've got a different project here. This is Blazor on WebAssembly. All right, let's go ahead and get this guy up and running. Now the code looks exactly the same. We've got a counter component with the same code that you saw before, same component model but hosted in a different way. All right, so here the behavior looks the same. We have a counter, have a fetch data page. This case is actually fetching some JSON data from the server, deserializing it in the browser and rendering this table. If we look at the network trace for this application, pulling down a little bit more stuff but some really cool stuff. If we looked in here, where is it? So mono, this guy, mono.wasm, that is a full.net runtime implemented in WebAssembly. And then below, you have normal.net DLLs being downloaded and executed directly in the browser. To show it, to really prove to you that this is actually.net code running in the browser, let's do this. I'm gonna do some debugging. Let's, now this debugging is gonna happen actually directly in the browser with the browser dev tools. To do that, I need to enable remote debugging with the browser. So let me just copy this command. Oops, not that. Copy that, good. And then we'll close all the browser tabs real quick and then we'll restart the browser with remote debugging enabled. And then we'll fire up the debugger again. Let's see if we can debug our C-sharp code that's executing client side. Okay, there we go. So here's the browser dev tools. Let me put this side by side with the browser. All right, now you'll notice I can see the DLLs in the sources for this application. You can expand the client DLL and see my counter component. You can even set a break point on the counter. Click the button and there, we just hit a break point in C-sharp code running on a WebAssembly-based.net runtime executing directly in the browser. This is something that we expect to ship in the future. All right, so that is Blazor in Visual Studio 2019. Cool. I hope you enjoyed learning about web development with the latest version of Visual Studio. Please download the bits and try it out. Fantastic, are we ready for questions? Absolutely. Fantastic, all right. So by the way, your questions are super important. So get them in, use the hashtag VS2019, we'll get them on the board and we'll make sure to ask them. If your question gets asked during the show, you will win an answer to the question. Hopefully. Well, hopefully, yeah, right. We'll do our best. Hopefully, hopefully, all right. So here is Aniket, I think I got the answer right. Talk about new CS Proj file. Is there a new CS Proj file or is it the same as old? Well, there is a sort of a newer flavor of CS Proj that we use in .NET Core applications that is much lighter weight. Like there's not much going on in the CS Proj files or we're in the applications that I created. You don't have to list every single file that's in the project. You get to use package references directly in the CS Proj. Yeah, we've done a lot of work to try and make CS Proj cleaner, lighter weight, easier to use. Fantastic, from Cal, when do you recommend to use Razor Pages versus MVC? I feel like that question, maybe you can help clarify. They're both great, they're both awesome technologies. So Razor Pages was introduced later and it's actually built on top of MVC. It's kind of a non-question because if you're using Razor Pages, you are using MVC. Every Razor Pages is actually running on top of the MVC infrastructure. Razor Pages is kind of nice because it's a page-based model. If you want a page, you just create a page and then the route for that page is just the place of that page on the directory, on the folder structure. MVC gives you a little bit more, I would say, decoupling in terms of how your project is structured, where your views are over here and your controller's over there. A lot of people really like that model. But both are great, both are testable, both can scale to large applications. I think Razor Pages is probably an easier place to start. If you haven't done any development with MVC before or ASP.NET Core, I would probably start out with Razor Pages. It's basically do whatever makes you happy. That's true. And whatever you would like to be happy with. I think you'll be happy with either of those. Yeah, yeah, whatever you'd like to be happy with. All right, so from Remi, Swagger looks great but is there a way to automatically create model classes based on Swagger endpoint, just like the old good one ad service reference? Just asking because I'm pretty sure it's possible in VS 2019. So there is some support for code generation in Visual Studio 2019 for doing client code generation based on an open API spec or a Swagger document. We're actually working on a major turn of the crank on that infrastructure for the .NET Core 3.0 wave where we will have really great support for doing MS build based code generation from your API. So it'll be really easy to, on every build we'll generate the code, it'll always be up to date. We're actually working with a bunch of really good community projects on that as well. And Swagger has some functionality that we're leveraging for this feature. Yeah, there's stuff that's coming. Awesome, next question. Is Blazor now officially in more than just the nice to have maybe in a pre-alpha mode? I air quoted that for you as he was watching. And fully supported in the new VS version? So Blazor started out as an experimental project, right? We were trying, playing around with WebAssembly. Could we get .NET to work on WebAssembly? Is that even possible? We weren't even sure if people wanted it. We've been doing that experiment now for a little over a year. We're pretty much at the tail end of that experiment where we're pretty sure that, A, yes, absolutely we can do this. And B, a lot of people tell us that they really would like it. It's still technically experimental right now, but I can sort of see the end in sight soon for the experimental phase of Blazor. The model of taking the same components and running them server side, where you manage all the UI interactions over a SignalR connection, we call that server side Blazor. That is shipping in .NET Core 3.0. Absolutely, like when .NET Core 3.0 ships, you can use that in productions. That will probably come first. And then as soon as the WebAssembly based .NET runtime is ready, we will then have production ready support for client side Blazor, running in the browser on WebAssembly. I was there at NDC Oslo when Sanderson was like, hey, do you want to see some code I wrote? Just a demo, just a little demo I did over the weekend. He was Pee invoking into JavaScript files because that's what you would do with Blazor, right? I mean, I was like, that's, oh my goodness. Yes, that's what it would be. All I know is it was a Fowler and Edwards. We were all just sitting there like this. What is this? And so it's pretty cool that it's advanced all the way to where I'm seeing a lot of people up taking this pretty exciting, I think. Yeah, we're excited about it. Having spoken, speaking of that, having spoken of my English is terrible today. Aala, what is the expected arrival date for Blazor on the client? Well, we don't have officially publicly announced release date. I can tell you that the client Blazor support won't be available with .NET Core 3.0. Like we'll ship .NET Core 3.0 first. And then Blazor client side, I expect will come sometime later. How soon later is what we're actually really actively working on right now? Like it really depends on how fast can we stabilize and mature the WebAssembly story for .NET all up. Stay tuned for that. Like hopefully we'll have answers to that question that are more concrete in the near future. Fantastic, just two more questions. Will there be interop between WebAssembly and JavaScript to allow for continuous delivery replacement of application functionality? So you can, there's probably two questions in there. You can of course call into JavaScript from WebAssembly. That works. You can call from .NET code into any JavaScript library, any browser API. In fact, you can even take those libraries written in JavaScript and sort of shrink wrap them in a .NET API wrapper, ship them as a NuGet package. And now anyone can call that library as if it was written in C-Sharpen.NET. There seem to be some hint in that question that they also wanted to be able to sort of dynamically update parts of the app. That is like a hot module reload kind of semantic. That is something that we have been talking about and looking at potential solutions. Nothing really concrete to share on that yet though. Awesome, well we're gonna finish with that. Thanks so much, Dan, for spending some time with us.