.NET Configuration In Depth | .NET Conf 2023

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello welcome to net com my name is Chris SS and today we're going to talk about net configuration in depth now I'm a senior customer engineer at Microsoft uh my day job is helping people do stuff with Azure um I'm just speaking here as myself I'm on all the socials I blog and all of these samples and my Dev containers for running everything are in GitHub under code bytes so I'm going to start talking about what is configuration how does framework handle configuration how does net and ASP handle it um what are configuration providers bindings options patterns we we got a lot of stuff but you know starting out like what are settings they might be values like retry times or Q length that we use to configure our application they could be feature Flags by by user or percentage where we're rolling out features or we're enabling features for people there could be Secrets like connection strings or registrations that we want to keep safe um all of these are types of configuration we're mainly going to focus on the first one but we're going to touch on the other two now historically we might have applied a lot of our config configuration at compile time where we have a configuration we we bake into the binary and that's what we use for Dev or we build a test build or a prod build um a lot of times nowadays we build one artifact we build it one time and we apply configuration at runtime and that's where all of the new power of the configuration system comes from like we get to be able to configure things dynamically and at runtime it's awesome so when we talk about The NET Framework configuration 4 47 48 web config and everything's a key value pair they strings we access them to a configuration manager dependency injection isn't provided um there's this transformation syntax but it's kind of difficult very easy to mess up we did have slow cheetah which helped us but it was very hard to unit test it was easy to leak Secrets it kind of looked like this and we would a lot of times wrap the configuration manager with you know an interface and a class so that we could dependency injection and if we wanted to get a Bool or an INT or date time out of these strings we would just have to do a bull parse and hope it didn't blow up and and I'll show you that real quick um you know I've got an a sample of framework and so you know our web config was yeah this XML and we would have to set these values um and then we would have a debug or a prod release where we could use xdt to transform certain Properties or to match you know so we if we had five different connection strings in our our Dev we would want to match one based on the name like my DB and then set the connection string attribute it it was a very interesting syntax now with net Core 5 six seven8 um it's been completely redone there's the idea of configuration sources so this might be a Jason file or an XML file this might be an environment variable or command line argument or something custom that You' made like tying it to a database these are processed by configuration providers and you define them in a certain order like I want my Json files first then my environment variables those get processed by the the Builder and you get a configuration out of it so for example if I defined my environment as Dev and my DB as Local Host in my Json file but I had an environment variable that overrode DB and then I had some command line argument I passed to change my log level configuration Builder flattens everything down in the order we defined it and then it's going to give us that bottom little box that give us our full rendered configuration you know Dev connection string and info and in addition to that it does support nesting and hierarchies of use so if we have ajacent object like logging log level default over here on the left it gets rendered out as a single key colon separated login colon log level colon default and so it can represent any level of you know structure and we can take those those keys and that configuration we can bind them to classes we don't have to worry about in parsing things for ourselves um net and the configuration system will bind it to a class for us and we're going to dive deep into this so if I just go to a console and do net new I get no configuration out of the box if I do net new web app or something in ASP I'm going to get Json provider configured with app settings I'm going get environmental variables command line arguments user secrets I'm going get things and there's so many different configuration providers besides Json and XML II we can have keys that are files environment variables and command line arguments in memory is awesome for unit testing um user secrets so that we can protect our development secrets and keyal to aure app config and so given just a normal Json file we can add um just a couple lines of code to reference that and add it to the configuration system same with XML same with environment variables if we Define these in our system we can access them uh even with a custom prefix and I I'll talk about the double underscores here in a moment um we can pass uh command line Maps so that we can have short names for some properties and I I'll show you that and then we can give it a directory and have it load each file as a configuration option itself and then we can set up just a dictionary to hold our inmemory configuration it's really powerful so like I said if I just do net new I have no configuration if I want to get some configuration with like Json for instance I can add some packages under the Microsoft extensions configuration namespace uh. Json and I can say hey Mr configuration I would like a conf configuration Builder and I want you to add Json and I want this file I made up config Json it could be app settings it could be anything I'm just making it config Json and it's just a simple file with a greeting and environment if I look at my program files I'm accessing that configuration and I'm just give me the greeting give me the environment and so now if I run it it's going to spit out that configuration and I can come in here and I can change this configur configuration and I can run it again and I've got a dynamic application I can now customize it whenever I want um we can add multiple configuration providers as we had in the example so I can have that config that's still set to Dev but then I can say also look at environmental file environmental variables so if I just do my normal. netr run it's stf but I can say for this command it's QA and I want to do a net run and so I'm not even changing files anymore I'm changing the environment and it's responding this is something we might use in a Docker file or in kubernetes you know through containerization where we're going to be a lot of times driving through environment variables maybe we want to do command line and so I could easily set my helps if you're in the right folder I could easily set what environment I want to be in via command line I could also set what I wanted via the environment variables because that's still listed but remember it's Json first then environment then command line so if I set something in environment and then I set something in command line it's going to take those changes and set them down if I set the same value in two different things the one that I've defined at the bottom of my my configuration list will be the one that wins now um I'm a big proponent of user Secrets I highly recommend that you that you use them um if you're not familiar with user Secrets um there's a whole document in ASP core about like safe storage of app Secrets um there's a secret manager tool it has you know all sorts of thing about how to manage user Secrets both in visual studio and visual studio code it's awesome um user Secrets when you set them up they'll add some sort of GD to your CS Pro all it is is an identifier it's not checked in and nothing's going to be I mean this this will be checked in in your CS project file but no secrets will be checked in or any or anywhere in your file system of your git repo so when I set a user secret I I just say set and I could set something like environment is going to be prod and so it is said oh your environment is now prod this is stored on your hard drive um in like your local settings like your your app data outside of your development environment so you're not going to check in any secrets um but it lets you just access and override environments and configuration like you normally would so if you needed to connect to something and in a testing non-prod environment and you wanted to be able to um debug something without having it in your file system where you might have saved you know it in a config file and checked it in definitely go look at user Secrets um another thing we can do and just to start making things a little bit more complex since we've got the ideas of configuration is let's set up some nesting a greeting with a message and a color and so if I want to access these I access these with that colon I talked about greeting colon color greeting message now I'm using a cool package called Spectre console uh and I've added the command line argument still just like before but I can I can do a net run and we've got a red hello world and I can give it an argument and notice I'm giving it the Das D greeting Cola and color so I can override those on command line just like before and I I can access these nested properties very very easily but I don't like saying Dash Das GRE and color what if I want to say color I want to make it nice and easy and refined well we can do that too I I I mentioned earlier we we have these mappings so just like when you were accessing uh command line before we're going to add a property called mappings and this is just a dictionary of a short name and then the nested name and so we can use this to quickly set nested properties without having to remember all of the values so we we can do it both ways and both are valid and but we still read the value with that nesting that doesn't change but that's a really nice thing um we can also do keep her file where we're accessing a file with the key name and then contents is the the thing and if you want to do nesting with files you have to use a double underscore and we use a double underscore we saw it in one of the screenshots earlier when you can't use a colon like on a file system or in in uh a shell where it's a delimiter maybe power shell or a memory object you would use a double underscore and that would be the same way um another thing we can do um is key Vault so Azure key Vault has got some packages that they've added and we can you know get the URL of our key Vault get the base name of it and we can say add Azure key Vault and give it that URL now I've already logged in Azure I've done an acli uh login and so for me it's using my default Azure credential which is me logged in if I was running this in Azure I would um use a managed Identity or or some sort of strict permission to limit things but I can come up here and you know with key Vault I can have secrets um and I can you know have information about it hello from Key Vault um and I can mess with my my message and if I if I want to make a new version and say um secret value and create that it's going to set that and now when I run this I should be getting a new message yeah hi there so this is accessing that secret information through key Vault now I'm not going to get into all the identity pieces there there's a lot of identity stuff to properly connect to services but um it adds it to the configuration system just like before we're accessing it the exact same way so it's a very unified configuration management system um now I've been doing a net new but you can also if you do a net new console you could add the extensions for hosting and do a host create application Builder where you can run your console apps inside of something like that and when you do that you start getting access to all sorts of stuff that you know you might expect from a application uh a web app so we're getting access to our configuration we're we're having a hosting thing so that we can monitor it we're getting a dependency injection so if we want to do like services and and inject or use configuration we're accessing accessing these things um just like we would you know through those examples that we built out U but it's a little bit more than just a net new console um and now let let's let's walk through a scenario real quick let's say we have a configuration for uh an application where we're going to make a PDF or markdown generator and you know I'm just printing out PDF template output I'm printing out values from this flat file um but what if I want to make it a little bit more reusable I can make this hierarchy where you know I notice I'm using the same properties over and over again like I have a PDF extension an output directory and template and a doc extension and output directory well I mean I can still access everything just like I did before I don't have to really change my program just change the keys I'm accessing but this is still got a lot of reuse and a lot of copying so I'm going to keep that same config file with the same sections but now I'm going to do something else I'm going to say options give me a section um I shouldn't name this option I should probably just call this configuration really but because if I put my mouse over um the parameter for file options uh you'll see what we get it's it's an i configuration so the whole time before we were dealing with an i configuration or I configuration route um and we were getting the whole thing now we're saying go look in your config and find a section called PDF and just give me that just give me that one section and so instead of those all those prints I was doing before I'm now doing it by section I'm I'm I'm starting to reuse my code and I'm saying I want to config with an output directory and a template and an extension I'm still dealing with strings everything's still a string everything's still from configuration and we can take this a step further we we can go a little bit further with that same configuration and we can get um a class so we can say I want to make a file options and if we go down here file options has those properties that I was talking about I want to I want to know that I'm I'm getting those properties and I updated my method to work on that class so I'm working on those those methods and those properties and so now I can say give me a section and and bind it bind it to that class so in this case I have an a class I've instantiated and I'm going to bind that class to that section so that's what bind does if I don't already have a class like an instance of a class I can say get and this is going to return a new file options that's been bound to Doc so it's going to do the bind for me it's like get Section new and bind you know when I do that and so you know we can operate on cloud now we can start binding stuff to real classes and we're going to take this a little further in the next section um let me go back here to the options pattern this is where we're going to start really diving in and we're going to not have those strong dependencies on configuration hopefully we can start pulling them apart and depend on our classes more so that options class we were looking at it needs to be non abstract with a public parameterless Constructor and you have to have public rewrite properties so just like with binding for an a a web API we got to have the same type of properties now when we when we use this eye options pattern we're going to have three choices there's an eye options which is a Singleton and then it won't support reloading and I'll show you that like if I change my configuration files or my app asure app configure key Vol while it's running the eye options won't reload and pick up the new value it get it gets calculated right at startup and it's just going to like stay there and not get updated it also doesn't support things called named options and I'll show you those are momentarily and then we have an eye option snapshot monitor one of them is a Singleton one of them isn't so one is a little bit more friendly for transient services and transient injection but they both support reloading and named options so let's just go play with those I'll show you what I'm talking about because I know um it can be a little bit confusing so I'm just going to run this application and we're going to um dive in um so this was a net new web API and so I added a method called providers just so we could see like like we're getting a bunch of stuff including picking up aspnet core andn net and app settings and environment variables we we're getting a lot of this stuff out of the box and and you can always find this um information if you're looking by uh doing a method called well I I just went through my config root and providers and I I asked for all of them by string there is another thing I'll show you where you can um do a dump it's really interesting where you can um get all of your configuration and like see where it's coming from there it is get debug view that will show you which providers are loading which values so you can troubleshoot that but um I can inject directly an i configuration into my page and I've got PDF and it's true and I can inject an eye options and I can inject a snapshot so I'm getting a the same data in all of these things and what that looks like like is you know if I injected my config it's literally in my in Constructor I'm saying I want an eye configuration and I'm doing the same thing we were doing in in program get a section you know I'm binding it to a part of my config and say give me a class out of it so I'm getting classes out of it and adding them in there for eye options it's a little different um for eye options I'm using eye options markdown converter I'm using a class and if I look at this um the mark converter just matches the style of the configuration we were looking at and the file options matches what we were looking at before it's just in this section here so I've got it in a section and the way that file stuff works is I went configure type T markdown converter and I told it the section I wanted it to bind to essentially I've registered this configuration class this options class with the dependency engine and so when I asked for an eye options or a snapshot or a markdown or um um monitor of the markdown converter it's going to go through the dependency injection engine and get me one so you know if I look at snapshot I asked for an eye option snapshot and it gave me one if I asked for a monitor IE options monitor now snapshot and monitor and options have one other difference I'm accessing it do value so um the eye option snapshot I'm accessing it and I get value monitor is different monitor is the thing do current value so that's the one that's a little odd and we'll we we'll play around with why that is so remember I went through all of these they all true what I can actually do is I can go change my config while the app is running I don't have to reload uh the application has not reloaded nothing's happening but I come up here F5 with my injected config I have I config going right into the page it picked up on that change how about eye options nope it's still true because eye options is a Singleton that only gets calculated when the site or you know gets initialized the other two have already updated to false now this one's still true and I'll show you why this is something I think people can easily get messed up with um I'm injecting a transient service I'm a transient service so this should be every single time I get a request I should get a new service but I made a dependency on an eye options in here so because I made a dependency on eye options what's happening is this is a Singleton it got created the very first time and it's using the old dependency every time I send a request so something to be aware of so close all of these and now let's Circle back to those named properties so the idea behind named properties is is not hard um when you register with the dependency injection when you like configure the same class the same thing multiple times so I configured it as a PDF I configured it for the doc section so I've registered file options three times for three different sections and so when I try to access it um there really isn't a way with the other ones like this is still I can still go to the configuration I can still get an object however I want but eye options doesn't really it just has value it just has value what monitor and snapshot provide is a get method so I can say hey I'm asking for a file options there's actually a couple of them give me the PDF one and give me the doc one so I can specify which name named option I want to get and retrieve and operate on so that's what named options are they they let us kind of pick which implementation of the thing we want it's pretty neat all right um just moving on real quick since we're running out out of time um one thing I love doing is azure app config you know I talked about things being Dynamic and um so I've got this data coming from Azure app config yeah black screen and white what if I'm doing web applications where I have containers or I have all sorts of servers and services that are running and I can't go into each machine and change a file I want to be able to use a service like Azure app config where I can manage configuration or features feature flags for multiple services and my entire application so right now my background color I don't I don't like that it's it's black on white let me flip it around so I'm going to make my my background white I'm going to change my font color to Black and then I'm going to update the Sentinel here and I I'll explain what the Sentinel is for in a minute so we've updated all of our our services you can come back here and boom it's updated with that new data I just set it to so the way that works is with Azure app config you you add the extensions um and you get a connection string you have a connection string to add your app config so I'm going to take a connection string to app config and I'm going to say hey configuration system add as your app config as a config store and use this connection string and also refresh my values but don't like you know let's say I had 100 values I don't want it monitoring all 100 that could be um intensive after a while so what I'm going to say is just watch one value called Sentinel if that changes refresh everything but you can cash stuff for 5 seconds that way you're not pinging constantly you're just looking every once in a while and and going to see if stuff's there that's really it I I've got a configure just like before and a section and I'm using test app settings and if we I don't know if you were Eagle eyed when we were up here all of these are test app settings so it's pulling all of these into a class um that's getting updated automatically when I update it in the cloud I think that's awesome um it's really neat and and you you access the values exactly the same way you access any other value so I'm accessing it here in razor pages so it's you know slightly HTML CSH HTML but I have a style tag and I'm setting my background Style just with inline CSS or C and I have an H1 that's getting updated and so when that um changes and I refresh it I'm getting the new values um and finally I want to get to the last two issues which are awesome um and for a lot of people so I'm going to try running my application and let's see what we get so this is Val this is printing out a web hook and a display name and some retry information what's interesting about this is you know I have defined my configuration in my settings class so I have a settings class and I'm using data annotations so I can say my URL is required and I have a Rex on my display name and I have a arrange on my retry times and there's been many times when I've you know spun up an application and it doesn't instantiate some Properties or some settings until a web request comes in and then it goes oh that's not set right and then then it blows up well what we've been able to do is add data validations right onto our classes so I don't have retry time set and you know I I have a really you know I'm just going to it's not the event and you know I actually want retry times to be five I really want it to go through so I'm gonna I'm going to rerun this and it won't even let me start it and I can I can like go through my logs up here and look retry times error must be between zero and three and URL length is too short so you know as I'm working on applications if I screw up my configuration if if I mess up setting the config for QA or for prod and I have bad values this won't even let me start running it's going to stop me and say Hey you messed up um and the way I can do that it's really nice um the way you do that is when you bind or you add your options and and you bind your section notice I'm I set some um con strings for the section name in my settings you can say validate data annotations this is a data of a data annotations method it's awesome and then you can add additional validations that you want so if you have some custom validations you want to add you can add validate to add some extra rules like oh I need it to be https and then you can say validate on start so when net starts up it's going to run through all the validations before it does anything else and it'll tell you if you screwed up and maybe you put the wrong URL in there that's HTTP instead of https I just got to find it is a little wordy at times that's part of the problem um now one of the big improvements in net 8 is when you're dealing with these validations here some of these can be done at runtime with reflection and so there's some new ways to do it at compile time and it'll generate um some of the code um right then so uh yeah compile time so it'll do source gener ation of a lot of those checks instead of the data annotation so it happens much more efficiently another thing you can do is you can actually make an I validate class so if you had some really complex logic that you wanted to implement to validate your stuff you can make this class and then in addition to the annotations you can add a single tin and and like validate or you don't need to do the single but you would add the validate options uh and register it with the the services and then you could do validation on Startup every time and then the final final thing I want to talk about just well maybe not final mostly final is what about if you know you still have people putting bad values in there they're still putting in HTTP and you need it to always enforce https well what if after we validated that configuration is there and we've tested that it's mostly good we can make fixes and we can update values after they've been loaded so that's something that you can do with a post configure so you can do a post configure say hey once you've instantiated this thing and validated this thing go ahead and say hey does it start with https and if it doesn't go ahead and make sure that it does go ahead and just update that property and replace the HTTP with https you could do something else you know you could validate um values that you don't want getting out or that you need to add some additional configuration to but you can configure things after they've been loaded now all of these samples all these things have been running they're in net 8 um and if you're you know I'm on an RC because it wasn't out the time of this recording but I've got a Dev container so as I'm playing with different versions of net I usually use the latest one which was seven and I I'll have like my ports forwarded and all my extensions configured I've got a net 8 one I set up with a Docker file that has all of that stuff that that I'm running net 8 in and um like it I I love running net in a container it's phenomenal um please if you have time go look at the documentation on net configuration uh they go deeper into marting your own custom providers and there's guidance on if you if you're a library author but um all of my samples are out on GitHub under codes.net configuration these slides are all out there um I'm on all of the the socials like I said but take some time please go download net 8 I think it's the best net so far uh I am a huge fan and I think you'll like it too thank you
Info
Channel: dotnet
Views: 16,976
Rating: undefined out of 5
Keywords: .NET
Id: aOXaBZFB0-0
Channel Id: undefined
Length: 29min 57sec (1797 seconds)
Published: Fri Nov 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.