ASP.NET Community Standup - Auth and AoT in .NET 8

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC] >> Hey, Safia, it looks like it's just us two. So we weren't expecting that, I don't think. >> Yeah. We were having technical difficulties right before this call, so this is like a live demo of conference talk. We're waiting on our co-host Jeff Fritz. Oh, he appears. >> Hey, here I am. >> Yeah. >> Hey there. Technical difficulties, challenges getting started, big thanks to our friend Myra helping us out today. How are doing, Safia and Stephen? >> Doing great. How are you? >> It's that one-up to a new version of.NET and we're almost done previews. So I've got this excitement of, oh my gosh, we're getting there, it's almost September. Release candidate season is coming. So I'm I'm getting excited, and I know you two have been busy. You've got new features that you're working on around authorization in ahead of time. Now we heard a little bit from from our friends David and Damian at Build about AOT, but auth is a big topic that I've started experimenting more with in.NET 7 and I've heard we've got some big updates coming for that. We should dive in and talk about it, shouldn't we? >> I think so, yeah. So I'm Stephen. I've really switched a lot of my focus to auth in.NET 8 and it's been a fun learning experience for me. It's a very deep complex topic. Like past, I've worked more I'd say like Kestrel and SignalR. So it used to secured, but we're not dealing with identity and stuff about later. So this is something we're working more with and I wanted to talk about two things in particular that I've been spending time on. Let's see. Maybe if we can start sharing my screen, we can just dive right in. But basically, are we sharing my screen here? Yeah. See, this is the problem with presenting on one screen. Inception moment. There's two big things I want to talk about, the first is map identity API. For those of you who've heard of like ASP.NET Core Identity UI, those are Razor Pages and maybe not everyone who's seen that. So if we just set that as our startup project and run it, I can give you a quick rundown what it is. >> This isn't those user ID pages that you have when you add the identity capabilities into your Razor Pages or MVC app. This is different. >> Correct. Right now, I'm just giving you a quick rundown for those of you who might not be familiar with the Razor Pages, what those look like, because this is a Razor Page. So I'm just going to, basically, it gives you a way to register an account. I can put my name in here. I can put my real age. It's using a real database unlike the in-memory database in my sample. So we'll just do that. It sends an e-mail, that's like something we'll be looking at later. Allows you to do some confirmation and stuff. Then typically, you can click to confirm your account here in the login flow, and then you can login or auto complete, get your management endpoints. You can get set up to a page, reset your password, all that. Great. The problem that a lot of people have is like, what if I'm doing React, Angular, a mobile app or desktop app? >> Yeah. I had somebody asked me this question today. "Gosh, real great to set up with Razor Pages and MVC, but for a SPA, what do I do?" Okay, go ahead. >> This is the answer to that question hopefully for a lot of people. So there's two things to note about this. One the authentication scheme we're using here as cookies, it works well in browsers, and another thing is that we're using Razor Pages. So if you don't have a browser, it ends up not being as good of a solution. But we have a very modular identity system which allows you to pretty easily customize it, and we are demonstrating this with this new thing called map identity API. You see in MapGet, MapPost, you can map various endpoints. In.NET 7, we introduced MapGroup which allows you to give a common prefix to a bunch of APIs. Then in.NET 8, we introduced this map identity API as user. >> Let me just pause you there for a second and back up. You said something there that you went by really quickly, and I'm not sure that the folks watching caught it. The API and interactions we have with identity right now are good if you have a browser. It's good if you're displaying a user interface, but where you're going is if you have an API. So not just an API, I'm guessing logging in and access minimal APIs, other standard controller APIs, and also maybe if I'm building like a mobile application and I need to login and I need that API endpoint. Is that's what you're talking about? >> Yeah, exactly. Then hopefully it will autocomplete the slag or stuff, but if not. Basically, it's adding a bunch of API endpoints, and right now I'm working outside of the ASP.Net Core repo and some pretty recent bits. One thing to note about the ASP.Net Core repo is that you don't get the nice swashbuckle UI or something. So that's what I was attempting to do here for a second. But I forget what the default URL is. It's like swagger or something. >> Swagger slash. >> Index.html? Yeah, maybe. Maybe something like that. Yeah. If we refresh this, we are going to ignore this for a second. Then we are also going to hopefully be able to switch to my other Windows desktop. This is bad on my side. Back to where we were. So anyway. >> We'll ignore the stagger UI for a little bit, and what I'm going to do the rest of this demo with is we're using this new HTTP feature that we've introduced to Visual Studio. Those of you who might have watched previous community standard have seen this. This is a little bit like the HTTP Rest Client plugin in VS code. Now it's been integrated in Visual Studio. I think writers had it for a little while. What this program is is a sample project in the ASP.Net Core repo like I said. We set up the AddEntityFrameworkStores with in-memory database, and then we've called this AddIdentityApiEndpoints. This is important for MapIdentityApi work. This adds services that we need. If we have 12 instances, it's calling a bunch of MapPost, MapGet, and it's adding register, login, and we'll go into what the other endpoints do. It's kind of corresponds a bit one-to-one to the Razor Pages but it's now accessible from spar or native app that you can do custom UI with. Really quick, let's just run this sample. We can send a request to an anonymous endpoint. I'm going to sign out really quick. I'm going to go get a little ahead of ourselves but if we hit an unauthenticated endpoint, you'll see we get a 401 unauthorized here. MapGet requires auth, hello username, require authorization. That's our authenticate endpoint that I just tried to hit without logging in. That requires auth endpoint. To make that work, we're going to want to pass the bearer token. The question is how do you get a bearer token? There's this thing called OIDC which is great if you're a Google or a Microsoft or a Facebook and you want other applications that aren't necessarily even written by you to be able to log in using your identity provider, that's good. We also recommend using Azure AD for this stuff and big apps. But certainly for developing and testing things with identity and for a lot of smaller apps, maybe like line-of-business apps, we think this is a great solution. Without further ado, you see that we got this 401 earlier when we hit that authenticated endpoint. How do we log in? First, you have to register. You can see I've already set up some pre-canned request here. I'm going to do example@example.com, and this is a password that meets all our requirements. If I was to send this request, they'll not have like probably capital letters or something. I didn't know why the scroll bar just went crazy. Sorry, guys. >> All the fresh stuff, right? >> Yeah, sure. You'll see you have requirements for the passwords, we're doing problem details so it must be at least six characters. It's got some alpha numerics and all that. Let's see. I have way too many windows. Sorry about that. Can you-all hear that? Am I sharing audio too with the bell? That's good. We'll send this request when we log in. We'll get that e-mail confirmation that we got before right here, and we can even copy that for a second so we can test that later. We'll copy this link. You confirm the e-mail if you want. This is something where you would typically write an IEmailSender yourself. Let's take SendEmailAsync. This is the same thing used with Identity UI, for what it's worth, to do e-mail confirmation. You can use Azure, has a service to send e-mail. >> Actually there's a couple questions here in chat. As you're going through, it's showing us that the API does let us log in. Folks are asking, there are similar identity questions when we're working with the user interface, similarly when we're working with the API, can we swap out to use Azure authentication as a provider or store our data in Cosmos DB instead of SQL later or something else on-prem? >> Yes. Identity has a lot of abstractions as far as user stores. We don't ship one for Cosmos DB that I know of. I think the only identity store that we, as the ASP.Net Core Team, ship is [inaudible] which isn't just SQL server. It's just anything that ASP supports. However, there are already community stores that support things like Cosmos and that's something that we've been considering, writing more samples for and stuff. So if that's something that you want, we can definitely talk about it. Also as of right now, there's no easy way with MapIdentityApi to use Google or Azure AD access token to log in and associate that with the identity account. But identity itself supports external login providers so you could extend this a little bit. I'm going to show that if we have time, you can add your own endpoints. That's definitely [inaudible] were interested in, is how many people want to use their own Cosmos DB stores with external login provider. We think that's a good pattern and that's why those systems support it. >> You'd want to be able to login with your Microsoft account, your GitHub account, your Google account. Absolutely. >> Exactly. Identity UI supports that so the system supports that, but MapIdentityApi with login endpoints that we have currently do not. But you can call APIs yourself and we can get a little bit into how that's implemented. But really quick, so we've just successfully registered this user and now we can log in using the identity login endpoint. One thing to note, I glossed over this quickly earlier. This identity prefix isn't hard coded in MapIdentityAPI that's coming from MapGroup. If you just call it App.MapIdentityApi, you would just be making a request straight to log in. It's an interesting thing there. Once we log in with this user, we get a bearer token and a refresh token. You see this expires in value of 3,600 seconds which equals an hour. That's how long the access token is good for. So if we wanted then copy and paste this axis token. >> I'm going to put that in the HTTP variable and then we can hopefully make that authenticated request. That's just the easiest earliest part of the demos, we have a user. >> The map identity API is just exposing what you configured in the Builder for configuring the identity authentication service. All of these things are a product of what was configured previously? >> Sure, you can, for example, here and add identity endpoints, this takes options. We can do options say, password options, there are of various kinds. >> That cookie duration length. >> Yeah. >> I think as you were talking about that's what got me thinking here. >> A lot of things are configurable like that. >> The key thing that I want to make sure that folks that are watching or viewers are hearing is they don't have to configure something different for their identity than what they've already been doing. You can just say Map Identity API and it will pick up those other configuration options you're already using elsewhere in your product and continue working, fantastic. >> To be clear Identity UI and Map Identity API are using the same stores, therefore you can use both in the same web app and you can sign in using whichever you want. I think it looks like I successfully copied and pasted the token and if I have, you'll see that I still can't make requests that's authenticated without sending the token. Here's the request that's just to get, I didn't set the authorization header, so it failed with a 401. I hope this is big enough for people to see, but it's not right. Then if you add this bearer token that we just got from the login endpoint which then you saw me store into a variable earlier in some that it should work and then you'll get hello example at example.com, and so forth. Then we can also see some information about the users. For instance, if we hit this manage info which currently in the Preview 7, the release is called accounts info, so we did some renames there, it'll be a breaking change announcement, you can see in all your e-mail whether it's confirmed and various claims you may have. The names of these claims are also configurable, some people don't like all this so that is the default has been an identity for a long time but you can use things that are shorter. Then you can for example confirm e-mail. Let's also discuss, so we're not going to wait an hour for our access token to expire but you'll notice that when we did sign in we got a refresh token and you're allowed to use it early. The way that works is if you're coming up near the exploration, we would want you to then send the refresh endpoint to or send the refresh endpoint. Then you'll get a response that's identical to what you had before. But you don't have to you don't have to write exactly you can just store the refresh token and not the user password in your app which would be bad for security because actually says mitigates that. This will also do a security stamp check, so if anything changed about the user it would fail. For instance I can repeatedly send this refresh request and it will continue to work because the refresh token it doesn't expire for several days by default. It's similar to cookies with the timeout so it has a much longer explanation than the hour that the access token normally has. However, let's say something about your account changes, let's say you confirm your e-mail or you change your e-mail. I'm going to resend the confirmation e-mail really quickly, I copied this earlier but I think I lost it in my clipboard so I'm going to copy it again. One thing to know is this is already HTML encoded so this should work if you get it in a normal e-mail client but we got to be careful when conferring e-mail here because if we don't >> While you're typing that, we've got a bunch of really good questions coming in there. Primarily on YouTube I'm seeing at this point, we'll be sure to get to, we've seen all your questions we're going to get to those in just a little bit. We want to make sure Stephan gets through what he wants to show us here and then we'll go through and chat about some of these. >> But I'm excited for the questions. Anyway, so hopefully this will confirm the e-mail will get a 200 response if I can unpause the debugger. It's probably mad that I added an extra forward slash, let's try. >> Two hundred, okay. >> Then now once you hit that info endpoint again, what we should see, because the access token is still good we should see that the e-mail is confirmed, exciting. What's notable is the refresh request that was repeatedly working earlier no longer will, so you'll be logged out in an hour maybe. I tried this earlier, never mind. Changing e-mail definitely will reset the security case stamp, there's a bunch of tests around this but we'll move on. The next thing we'll talk about is a 2FA which you can set up. For this user we'll see that this two-factor enables false switches. The default same as identity UI when he set it up and then you get this shared key which typically is used to display a QR code then goes to authenticator app. Then in that authenticator app every 30 seconds or so it shows you a new code. We have some instructions and we'll document this, it's also there and, I didn't UI which is here's how you set up a QR code generator. But for the purposes of this demo, I'm just going to run the code in, used to be called.NET Interactive now it's Polyglot Notebooks, so I'm basically taking the current time, figuring out the time stuff, doing some TO/TP, I forget exactly what that stands for, time as part of it and then it gives you a code. Then hopefully with that code we can enable it. Here I have an old code, so if I send that it's going to reject it, it's going to be bad requests, the TFA token you provide it with request is invalid. But if I put in the new code which I got less than 30 seconds ago, it should be forgiving enough even though I've taken a little bit of time talking. Let's hope it works right. It does. Now you'll see that is two-factor enables true, we've got a bunch of recovery codes, I'll copy one of those just to show how that works. You can use the recovery code and you can log in that list. Note that now that we've been able to pay out, we can just rerun the login on point and didn't fail because it requires two-factor, we just talked about. Now along with the password if you want to work if you get this requires two-factor result, you send the password together with the two-factor code or the two-factor recovery code. I guess it makes more sense to show the mainline scenario first, so let's get a new two-factor code. I can just rerun this because the shared key is the same as before and then I can log in with that and then we get a login like before. Alternatively we can use one of these recovery codes that don't expire because there's only ten of them and you can't reuse them. You got to go and then if you try it again it's going to be, you're unauthorized. Then if we check the info endpoint again, you'll see that instead of 10 recoveries codes left, we have nine. That's how it works. There are options to regenerate recovery codes and so forth. I'm not going to go through everything because I think I'm already out of time. >> The process here. There's a ton of questions that have commend, you want to take a minute or two here Stephen and take a look? >> Absolutely, for sure. >> Lots of folks are very interested in how this is going to integrate with our existing applications. Is it Jimmy Scott on YouTube asks, with respect to.Net or identity and authentication, is it suitable for multi-tenant applications or do you think that Darwin Day or OpenIddict are better options? >> Yes. I do think that for multi-tenant applications which implies that you want single sign-on is my understanding for a different and tell me if I'm wrong. >> Yes. >> For different applications in that case OIDC server is nice and there are a lot of client libraries around that so I think that yes, if you're not doing authentication in the same process/application as the rest of your app, an OIDC server makes sense and whether you like OpenID or whatever we think those have a place. We're not trying to replace any of those. >> You can make identity work with this if you just assign a claim that is the name of the tenant that these folks are associated with and then use that tenant to filter appropriately as folks login to the application or route appropriately. >> Yes. I guess the key here is that right now this map Identity API will sign in with two potential authentication schemes. This is the one that existed before which is the application like cookie scheme and then there's this new bearer token scheme. Like one thing that I will note that maybe I haven't made clear enough about this token right here is it's not a job fair token. It's actually more similar to a cookie and it's like encrypted stuff but it is still a bearer token in that it's part of like the bear authorization header and so forth. It is tied to the application, like you can only authenticate things using that applications authentication schemes. In this case, it's those two. It's not ideal for authenticating outside of that ASP.Net Core application. >> Some other questions coming through here. If a user got a token and that user was then disabled and invalidated does it also invalidate the token? >> No. It invalidates the refresh token. Basically, if you change the security stamps so eventually the access token will expire in an hour and this is pretty similar see how cookies work so we're like with cookies when you sign out right you're trusting the client generally the browser to respect the fact that you told it to delete the cookie but you know if someone really wanted to keep using a cookie after you signed out, they could just save it and continue sending it and because we don't take a database hit on every single request, only on the refresh requests the access tokens don't get invalidated. They just expire. >> That's not too bad. If you can dial back then how long that access token is valid, in your identity configurations if you want to reduce that attack vector. >> Yes. To be clear about this, so this gets into a little bit of how identity endpoints works. By default, I'm calling this Ad Identity endpoints than adds both the cookie and the bearer token authentication. I'll show you really quick that it's possible to sign in with cookies. There's this use cookies equals two and this is going to fail at the molecule they just enable two affair but I quickly get a code it would work, but let's see how fast I can say it. Two hundred so it worked. Now I can make that original request that failed because it didn't have any bearer token header and it's going to succeed and the reason it's going to succeed is because Visual Studio just automatically sends cookies even if it doesn't tell you that it is. If you put a breakpoint here and then we did this request we can work our way up the call stack and like look at the http context and so forth and by the way shout out to James to like put a bunch of debugger display attributes on HE context which makes it way nicer. You can request cookies and I know this is super small probably I was going to try to zoom in. Anyway, cookies. Now, we have the application cookie and so forth then yes, something factory stuff. >> There's a handful of questions that are also here asking this feels like this is getting us closer to being able to replace identity server 4 with built-in identity. >> Yes. I mean it does fill the gap for certain scenarios for sure. It's simpler than an OIDC server but for a lot of scenarios I think it is a suitable and then to finish up my last thought, this identity endpoints is adding cookie and bearer token auth but like all of these are public APIs. Another way to do it and what I was about to copy and paste and show it, is like you could instead of calling an identity endpoints here, basically just call AddItem core add API endpoints to the identity builder that is returned by identity core which I'm pointing out on my screen which you obviously can't see you but I can't do my cursor either. Oh, wait I can. I thought I'd use the hover text, anyway returns to my identity builder and then here, what we did is we only added the bearer token scheme. If we do that and remove this and then restart everything, everything that worked before will still work to an extent except for the cookie stuff. That's basically what it comes down to. You can do that. It's going to complain because I did the weird thing with the password. >> Then if I try to login with the cookie like I did earlier wait because I couldn't lecture quote. Yeah I should remove that break point and then yeah so then then you'll get a hopefully helpful error from the cookie login which is like there's no relevant authentication handler for that. But the point because you're talking about earlier also customizing the expiration on this you would actually be changing the bearer token options not the identity token options that's like an often that's relevant to the authentication scheme which you can tactically use without identity. You can just call HTTP context.signin identity constants bears scheme or whatever and they continue to use this so and then you can set bearer token expiration and obviously takes longer than a second but you get the point >> There are a bunch more questions about how this is going to integrate and I know we're still early in the development of adding the identity APIs and I want to make sure we have time for Safia. >> Of course. >> Because there's a bunch more we want to talk about it with Safia. Can you follow up with some of the folks on YouTube here and in the check in there as when we transition over to talk to Safia. >> Absolutely and yeah I have a hopefully a fun segue that I talked to Safia about so when we're adding all these identity endpoints remember how earlier I said you can just sign in with the identity we actually want to. Let's see I don't have an H3 context here so I'm going to wait but you would be able to in your own endpoint do like return types results.signin and boom and then you can change, you can just make the bearer token your default scheme and you'll get that nice response refresh token the access token all that and then if we want to do this, I guess the point I want to make is if we look at all these new map Identity API endpoints it's got some fun stuff with some auto generated code and I think software can tell us a little bit more about like what is this code generation and why that's calling incident my register handlers and so forth and hopefully you weigh this endless sorry for riding long. >> Oh no that was great. I've been sitting in API reviews where Stephen has showcased his work over the past couple of months he's been doing a really great job on the identity stuff along with Jeremy who I think is in the YouTube comments who's our PM who's been answering questions and stuff so it's really nice to see your demo and see everything come together in the end. What I've been watching the PR and the API reviews come in so it's pretty neat to see all makes such a big story and.NET 8. The other big story in.NET 8 is Native AOT and some of the work we've been doing to support ahead of time compilation for.NET and we've been talking about this a lot over the past couple of months Jeff I think you mentioned earlier that David Fowler and Damon Edwards did a presentation at Build about some of the work that we've been doing I think there were also at one of the past stand-ups talking about all of the Native AOT work that has been going on so I recommend folks check out those videos and our blog post and all content. Look at some of the features that we've been building out and while I was getting ready to do this stand up I was thinking a little bit about how I would structure it and one of the things that I thought would be interesting would be to go through the experience of taking an application in.NET 7 upgrading it to.NET 8 and then enabling publishing with Native AOT support and talking through some of what works some what doesn't and where we're going to go with native video team moving forward. >> Sounds good. >> Just like Stephen I'm going to be living in the Code Editor for most of my presentation so if you want to share my VS Code window. Awesome there it is. Cool. I'm starting off here with an application that I've used in the past to demo some.NET 7 functionality it's available on my GitHub it's the training API repo on my personal GitHub account I'll try and post the link to that later so you can see the work. But what I've done is I've taken this application and I have upgraded it to.NET 8 so I've got my TFM upgraded and I've got all of the packages and dependencies updated. Most of the code has stayed the same so some of what this application is doing it looks like I'm using an in-memory database with the [inaudible] to maintain my data I've got authentic and with Jarque-Bera based authentication I've got swagger to showcase my endpoints with open API and I've got a set of APIs here that are all registered using minimal APIs and for those who are interested this is a quick little app to help a local gym manage all of their trainers and their clients. Once if this app it's been written for.NET 7 and when upgraded to.NET 8 I've done all the expected work of link trained HTFS and what not and I've also set the publish AOT build property to true in my application so when I hit "Publish" it's going to compile head of time and let's see what happens when I run.NET filled in my application so let's go ahead and do that. Now one of the things that you'll observe is that when the publisher IoT build property is enabled in my application that was not supposed to happen let me do a clean and let me do a build again live demos of am I right? >> Yes. >> With the publish AOT flag enabled the linker will run at the published phase of my analyzer and in particular what I'm trying to showcase here by running.NET build is that there is a linker analyzer that will run at build time they'll statically analyze the code in my application and observe anything that might be a problem for the tremor and notify me. What I've done here is I've just done the build stuff in my application I can see that I've got a ton of warnings from the linker and they all seem to be related to the map action endpoints in my application some stuff going on would like map post mapped to leave map put. That's a bother now one of the challenges with the experience or the implementation that we shipped from minimal APIs in.NET 6 and.NET 7 is that it takes big advantage of reflection and dynamic code generation as part of its functionality. Whenever you implement an application with minimal API endpoints at startup we take a look and we use reflection to inspect the Rack handlers that you've provided understand what types of properties and parameters you've provided in your incoming route handlers and then generate code that can essentially take a look at the HTTP context and resolve parameters of those types from the HTTP context as well as write responses to the HTTP context depending on what your application is returning. All of that is using reflection to the inspection of your route handler and understand what parameter should be bound and then dynamic co-gen to produce the actual code that's going to read the HTTP context extract whatever arguments from the route or the query or the JSON body and then write out to it. All of this is not inherently friendly for the trimer so it's one of the first things that we have to pursue for.NET 8 was figuring out a way to remove our reliance on reflection and dynamic co-gen as part of minimal APIs and we did that so one of the new things that you will see in.NET 8 is support for the what's called the request delegate generator and I'm going to jump back into my CS Proj here I mentioned a little bit but I had enabled publish AOT in my application but I did do something else that was a little sneaky which you'll notice I have online nine here set the enable request delegate generator flag to false and that's actually what's causing me a lot of issues here I have disabled the compiled time it co-generation for minimal APIs that we introduced in.NET 7. If I take a stab at removing this, call out this commit what I should see now is that doing another filled clean and build my application will remove those linker warnings and that is because we are now using compile time based code generation for our minimal API so I've got no warnings here at least at build time. >> Let me just make sure I understand that right. All the code that you were using reflection to generate going to have in memory at startup time you just move to build time instead. >> Yes. >> That's awesome. >> It's almost near term we've been using has been shifted left or a lot of these things were things get moved earlier and earlier on so everything that we were doing previously using reflection we're now doing at compile-time using static analysis with Roslin APIs and instead of using dynamic code-gen with link expressions we are now in video codec pile time using an incremental source generator. One thing that I'll point out to people if you haven't source generators a ton in your applications in the past here's a pro tip there is a built property called emit compiler generated files when you enable this build property in your application it is going to spit out the source code that is produced by your generators to your intermediary output in your application so if I go here training API, obj, debug, net8.0 generated is the directory I'm taking a look at and then the name of our generator is Microsoft ASP.Net Core HTTP request delegate generator we make really great names here. >> Long names. >> Long names. >> That is our resident API review guru so it's got some more stories to share about some of the API names that we've had to review over the past couple of years. Yes, let's not talk about our service provider service of we have fun times in API review. But what's really cool is that you can actually take a look at the code that is generated by the requests elegant generator and you can inspect it yourself. You can see some of what we're doing here we are leveraging a new preview feature in the compiler that you may have heard about I think in previous stand-ups called interceptors. Interceptors provide the functionality to annotate a particular implementation of the method. Here I've got this map gets zero method and I've got this intercepts location attribute which basically says, hey, for the MapKit invocation that's defined at this file path, at this line number and in this column which is line number 42 column nine. If we head back to for source code for programs yes we'll see that this matches with our clients MapGet call. I'll say hey if you encounter this line I would like you to call this code that's been generated pile time instead of the MapKit invocation that's in the framework which uses reflection and link expressions to generate code instead use this one that have actually generated in my source generator and invoke it. If you're curious you can dig into the actual implementation for what's produced by the code generator but you can actually read through it and what I think is cool is like you can see what the structure looks like for how we resolve things from the http context I mentioned earlier that part of what we do is inspect the parameters of your handler so here we see you have an ID parameter that's an integer. Well he probably intended to resolve that from the route parameters or as a query so we're going to try and extract it from the router query. We're going to do some checks to see that you've actually provided it since it's a required parameter. You can actually read through all of the code that's generated here understand step-by-step what your minimal API is doing. >> Safia, there's a question that's come up once or twice here in chat and it's a decent question. All this code that you're generating is it adding just time to the build process to generate all this code? >> That is a great question. You're totally right as a result of this some of the time that you would have been paying the cost for at startup you are now paying the cost for compilation. It does increase your compile time. Now what I'm not going to say this is going to blow your compile time. One of the things that we've actually taken great care of is making sure that the performance impact of adding this generator to your compilation is not great so it's an incremental generator. For those who are not familiar, assertion earners have existed in two iterations, the first implementation was kind of I source generator and then the second is this incremental generator which is a little bit smarter about caching server instances so that when you are if you haven't modified a particular syntax in your application particularly if you're running a Visual Studio the generator is not going to keep running and reproducing code as aggressively so the generators incremental it takes advantage of some caching properties and then also we had a benchmark so you can find the benchmark code for the generator and the ASP deck or repo and we try to make sure that in its actual implementation. We take advantage of caching so for example I mentioned that one of the key properties is that we inspect the types in your application to determine what shape they have and how we might bind to them and we actually will try and compute that only once and then cache it. If you have a poco like a to-do or a task list that you're using and multiple APIs for your application we'll run the code to compute whether that might be a parameter that is probably coming from the JSON body or something that is a service and we're on that once and then cache it and so every time you reference it in your endpoints we're not recomputing it. Yes, the long story short is that the shift left does mean that you're saving time at startup which I think is valuable if you're deploying your application, typically the compile time cost is a onetime cost but cost you might pay more frequently. >> You as a developer, hey who cares if you take a couple extra milliseconds to compile that one time if it means dozens of seconds on the front end for all the users interact and that's a good tradeoff. >> Yeah and then again I want to emphasize that's doesn't mean we're like punishig you as a developer by link dramatically increasing your build time. It's still a fair trade off >> There's another comment here in chat I want to makes sure that we touch on and you did answer and Rizwan had a question about gosh you're going to have to go regenerate every time you touch this file but you've got it cached and you mentioned you're able to incrementally improve that but there is a question here from big dub on Twitch I can't believe I just said Big Dub on Twitch asking well how does this affect our unit testing process if we're generating some of this code or we're still able to unit test the code that we originally wrote but instead it'll be rerouted over to what's being intercepted and deliver. >> Great question so I think it depends a little bit on how your tests are structured. In this demo application that I'm showing you it does actually contain a test project which I can open up and and there's two layers of testing one of them is testing for a training API service so I've got it if I can find it, training service so I've got a trading service that does the actual business logic of my application and I might unit test that so I can continue to unit test that in its own it's not strictly related to minimal API so whatever testing and functionality I have for that will continue to work. It runs at compile time as well so if you are referencing MapKit endpoints in integration tests which are showcased through this project as well those should also continue to work as well because that interceptor will be able to map the replacements appropriately so this shouldn't affect things too much particularly if you're in and testing individual components within your application if you're doing integration testing would like the NBC testing package it should work much the same. >> There was a further question about you added open API to this project that was something that you added not strictly required to get this benefit that was more to generate your swagger and points and all that. >> Yes and that actually leads me to the next portion of this presentation that was a really good segue whoever asked that question. I've run the linker analyzer at Build Time. I haven't actually run a published up yet so I'm not able to see all of the trimming and IoT related errors or warnings in my application so let me do that now and I'll preface this by saying but I'm leading to is one of the first things that doesn't work super great in my application when I've got a native IoT enabled which is open API and swagger. If we take a look here is me actually running the publish step and you'll see that I am getting setup warnings from the linker itself related to references to swash buckle, I use peanut core swagger.net open API. API explorer in my application if you're familiar with how the open API infrastructure and ASP.Net Core works you'll recognize some of these types and assemblies as related to supporting getting an open API documents out of my application. It's not inherently trim or native AOT friendly for much of the same reasons that the requests are the minimal API layer is not which is that we need to reflect or use reflection to understand the parameters that are provided to our endpoints in order to be able to produce the open API document that presents them so this is one of the first things we'll encounter that we don't have like a super neat solution for at the moment like we do where you can just enable their customers and generator and things will magically work in your application. So native AOT it's a big effort it's not like we can just spend a couple of months working on it and then everything works for all of our framework implementations and all of the open source library. We will encounter some things that don't work open API and swash buckle is one of those areas that does not support the native FAO ts f.8. There's some interesting ideas I've prototyped around using source generation to produce opening API files at compile time in much the same approach that we're using for minimal API so yes unfortunately you're not going to be able to use any of the open API infrastructure with native AOT. If you hit these issues one of the things I would recommend and one of the things I'm showcasing in the demo here is that for some scenarios open API might purely be a development time experience so something that you as a developer are using when you're debugging and building contest your APIs. I actually have been using HTTP client that Stefano showcasing earlier pretty extensively so I don't use Swagger UI as much now that I have embedded at my editor. One of the things that you can do is omit. >> Compilation or introduction of those openings gang-related types in your application if you're building it into release modes so that is one of the things that you can do through. Again, not an ideal solution. This is hopefully something that we're going to continue to improve on in future releases. But what I've done here is I've stuck all of my open API-related things behind and its debug. It's not going to be compiled into my published release bits since for my particular situation I don't need it in a production environment. There are some situations definitely where people want to have the open API Jason as part of their deployment so that other developers can see it and examine it. But that's something that we hope to support in the future with some of this work. >> That's going to be much shifted also. >> Yes. Also, things to left shift and work around but for now this is how I'm approaching it in my application. That was a great question for whoever. >> I'll grab that name real quick. The native AOT stuff really it's moving things, it's left shifting things so that we can get that better startup. Really, this is one of those things that you want in your container app so you get that instant start in faster startup of these things. Removing the reflection is only going to make it better for everyone. >> For those of you who are curious to see some of the numbers behind this, I recommend checking out the Preview 3, the.NET 8 Preview 3 blog post has some numbers that showcase some of the improvements that you get for turning on native AOT in your application. The.NET 8 Preview 7 blog post shows some of the improvements you get with enabling the interceptors-based minimal API generator in your application and we've got public performance benchmarks that you can check out as well if you're looking to understand the numbers behind this. >> We know our friend Steven is going to be putting together a performance blog post coming up here in the next month or so is usually do for something in a release candidate cycle. >> Yes and Brennan on the ASP.NET team also will publish an ASP.NET specific performance blog post so keep an eye out for that as well. >> All right. >> I do have a couple more things to showcase. We can jump ahead if we don't want to do the play by play. There's two other things that we need to address in our application. One of them is the fact that I am using EF Core. EF Core is one of those things that is not quite set up for native AOT in.NET 8 there are issues on the EF Core Repository that are tracking the work involved. It's a pretty huge undertaking, but if you're curious about that, check that out. As a substitute, instead of using the EF Core, what I can actually do is take advantage of some of the more lower level data access APIs that exist. There is new APG SQL which is the.NET API for interfacing with Postgres, and then there is also the Microsoft data SQLite library or package which is for interfacing directly via raw data access with SQLite. Both of those are native AOT friendly and what I've done in my application is I have swapped my dependency on EF Core for a dependency on the SQLite APIs and I'm using that here to write SQL, which I really had to dust my SQL skills. Please don't judge if this is not the best SQL ever. But I have swapped my API here for seeding data into my database using SQLite and I've also changed the implementation of my training service to take advantage of the SQLite library which is native AOT friendly. Then the last thing I wanted to talk about this is not new in.NET 8, but you can't take advantage of the adjacent source generator as well. It follows that same shift left philosophy. It involves a lot of serialization and deserialization which occurs in inspected pipes to understand how they shouldn't be serialized or deserialized so we can take that same philosophy and shift left with the Jason source generator. I've gone ahead and configured that here. There are wonderful docs on how you can involve the Jason source generator in your application. That was the process for me taking my.NET 7 app and then making it native AOT friendly with.NET 8. That just covers making things compatible. There are also new APIs that we introduced in.NET 8 to make your application size smaller. One of them is CreateSlimBuilder, which is another wonderful artifact from our API review sessions. By default when you create a web application instance using this minimal hosting API the web app that you get is configured with some defaults. You get a developer exception page, you get a ton of sane defaults. They must always be applicable to you like you might not even a developer exception page in production. You might totally be fine just getting rocks options throughout you even when you're developing locally. The CreateSlimBuilder is a web application liked. It has fewer things just the essentials for building your API. It does automatically register authentication and authorization middleware if you have them in your application. That can help reduce application size by reducing the number of dependencies you take on when you implant an application. There's also CreateEmptyBuilder, which configures an empty builder so no defaults are set for you. You can use that if you want super granular control over what's set in your web application. >> It's the do-it-yourself model, isn't it? >> Yeah. It's the do-it-yourself model. There's other APIs that we've shipped to reduce the dependencies you take on HTTPS in your application. That was a little bit of the whirlwind tour of it. We talked a little bit about how you can take an existing app upgraded to.NET 8 turn non-native AOT. We talked about what works really well and what we've added support for, then we've talked about what the path forward would look like. There's tons of opportunities and things for us to do in this native AOT EF Core around. >> Support with ORMs like EF Core talked about around open API and then also we've shipped new APIs like this create slim builder and Create empty folder to help you have more fine-grained control over how larger applications are. >> We talked a little bit about EF Core has a little bit of a challenge with IoT. I'm assuming dapper with how much it uses dynamic interactions. It's going to have similar challenges to be native IoT compiled. >> I think there's been some interesting experimentation on that front as well, but this is definitely a little bit of a grand upper and lots of libraries collect from this. I've seen MVC referenced up quite a bit in the code comments. It uses a ton of reflection and also will load assemblies dynamically for using application parts. We've done some a little bit of experimentation that passed to see what it would look like to make MVC, native IoT compatible. But it's a fun journey. I've enjoyed working on this stuff over the past couple of months. I want to shout out all of the different individuals. I mentioned the interceptors feature which is coming as a preview in the compiler. We've done work with folks on the run-time team ASP.Net Core, EF core. It's really cool to come together as a wider team, and community and push for this work. >> Just to throw back. You mentioned the interceptors there. Did you have to turn on the interceptors preview feature in your project? >> Yeah. Interesting. This is actually one of the design points that I was quite passionate about making sure it was veiled down. As long as you enable publish IoT, specifically for the request delegate generator and the configuration binding generator which is another shift left generator that we're shipping and Donna-8, you do not need to set the interceptors preview feature flag. For those we automatically will set for you in the Web SDK. This is as a user nicety to avoid having two properties to do one thing in your application, CSPROJ2. In that particular case, the feature flag is implicitly set for you, but we will be documenting the fact. It's an interceptors under the hood to get some of this stuff working. >> Right now, the publisher at C is the only way it's enabled them to request tell you generator. I remember there used to be another property. Is it still there? >> If you don't care about any other native IoT things, you can just enable request delegate generate, true and that will turn on the compile-time co-gen feature. You can take advantage of the performance improvements that you get with RGG without opting in to the whole publish IoT experience. >> I have to enable the compiler feature then. Sorry. >> If publish IoT or the enable RGG flag is true, you don't have to enable the compiler feature. I will say that, not everything that works with run-time code-gen works with compile-time code-gen. There'll be something not impossible, but I can't quite pure reason through or if your endpoint is returning anonymous types. That's not statically analyzable at compile times. That's not a experience that we support. If you are trying to reference types in your compilation that are private and don't have friendly access, it's another stereo we don't support. As you migrate your application, you might encounter some warnings that basically tell you, hey, we couldn't generate this endpoint at compile time, we're going to generate at run-time instead. Those are the areas that we're working on improving. >> Very cool. >> Well, there you go whirlwind tour. >> I should call out here. I mentioned dapper earlier. Michael on YouTube is highlighting. There's already a dapper IoT project. I'll have to check that out. Thanks for [inaudible]. >> [inaudible] is using interceptors and its implementation, if I'm not mistaken. It's happening. >> I am just starting my review. I'd like to wait to look at and start implementing things for next versions of dot NET as we hit release candidate here. We are right at that sweet spot where I'm excited to take a look around at all the cool features that we've been talking about and start implementing them in various applications. >> Between all stuff that I shared I think you're going to be very busy, for a few days with all of these things. >> Good. That's right. Let's get that running. Rizwan on YouTube asks, are generics supported? >> No. That is another one of the limitations. I assume you're talking about the compile time based RGBA approach. >> It depends on what you mean because requests or map eidetic uses it. It has a generic parameter, but you have to do work rounds. >> It's not directly supported, so if you reference generic parameters in your map action points. We don't support code-gen for that. We have done a little bit of design work to discuss how that might look like in the future. That's definitely on the docket, but I know stuff and that was one of the things you run into and you have to get a workaround going because you had a generic reference to one of your parameters and that's [inaudible]. >> But I definitely encourage any library author who's using Mathcad or map posts to use that enable RequestDelegate generator thing because it's trip friendly if you do it and it works. >> You try to report bugs especially once the RC1 comes out, keep me busy fixing bugs. >> Please try out the map Identity API stuff. It is hot, fresh and we've only got a handful of community members using it. I'll admit that there had been some bugs, so I hope to get as many of them quashed before RTM is possible. >> We're right at the beginning of this shift left movement. We're releasing more happened. There's lots of dot NET versions after this that more can be rolled out through. All good things. I like Stephen's point. Let's get some feedback and show performance benefits of all of this coming through. Very good. Thank you Safia, thank you Stephen, this is great. Like I said, I'm excited to look through this a little bit further and get my hands on some of these performance improvements. The identity stuff is a big thing that I'm running into with an application that I'm building. I'm very interested to see how that works. Very cool. I think, does that brings us to the end of our time together today? I know we're a little bit over. Well thank you so much. It's been a pleasure chatting with you. Just to recap. Safia, can you go over your role. What it is that you do on the team? >> Yeah. I'm a software engineer on the ASP.Net Core team. I spent most of my time working on minimal APIs, off API, some MVC related things. API layer of ASP.Net Core is my specialty. >> Very cool. Stephen. >> I've been on the ASP.Net Core team since I graduated college in 2005. I've done all. Back then it wasn't Core. Is the status MVC all that stuff. >> But it was K. >> It was even before Project K. But I got to work on some of the early stuff. You can blame me for a lot of DI, kestrel and stuff of that nature. Now I'm working on off. Which I'll admit I'm a little bit needs to as well, but I've been quickly ramping up and it's a fun space. >> Very cool. Thank you both so much and we've got dotNET Conf coming up in a couple of months. I think we're all looking forward to that and talking more about all the great stuff with dot NET8 when it releases. I think we're wrapping up there. Thank you both so much and it was a pleasure chatting with you. To everybody out there on chat, have a fantastic rest of your day. We have some source that we shared some samples there that we'll post some descriptions and links to those just below here so that you can check out more from what Safia and Stephen showed us. We'll catch you later friends have a fantastic rest of your day. >> Bye.
Info
Channel: dotnet
Views: 9,199
Rating: undefined out of 5
Keywords: aspnet, dotnet, AoT, aspnetcore
Id: m_8zd9GkGCE
Channel Id: undefined
Length: 73min 57sec (4437 seconds)
Published: Tue Aug 29 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.