[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.