Setup Plugin – Part 1

Setup Plugin – Part 1

I’ve been trying to develop a slightly better approach to application configuration. The process we all go through now works, as far as it goes, but I think it could be better. For instance, it would be nice to have a UI for editing an application’s configuration. The problem is, creating those UI screens, on top of whatever UI your application already needs, is both time consuming, and tedious. Also, all that extra code adds complexity, and bloat, to your project. Finally, as the application’s configuration needs change, over time, that extra code becomes an additional maintenance burden.

Still, the fact remains that having a nice UI for editing the configuration would be awesome! I mean, think about it, we could add validations to ensure nobody chose an invalid set of configuration options. That might make it less likely that anyone would brick and otherwise working installation, by accident. We could even get fancy and add contextual help, to prompt us when we find ourselves muttering: “what was that ‘XXX’ setting used for again? Darn, I gotta go look at the code again!”. We could even add some code to generate reasonable default values, in case the configuration file was accidentally deleted, or mangled in some way.

Oh, you know what? We could also protected sensitive configuration options with encryption, transparently, and never need worry about the security aspect again (make those security audits a little less painful).

So, having sold myself (again) on the concept of a UI for editing configuration settings, I decided to layout a short list of what I was going to try to accomplish. The way I see it, what I need is:

  1. The ability to generate a set of UI screens, on the fly – using either JSON as a source, or failing that, a C# POCO model, that could then be bound to the JSON.
  2. The ability to apply validation rules to that generated UI – so we don’t break the installation with any invalid settings, or combinations of settings.
  3. The ability to apply role based security to the UI, so unauthorized people can’t view sensitive settings, brick our application’s installation, or worse!
  4. The ability to make changes to our setup, and UI, quickly and easily. Ideally, without requiring a new build, but, at the very least, let’s try to isolate the changes and recompiles to one or two classes.
  5. The ability to house all this as a plugin, so we don’t clutter up our project’s codebase with stuff that doesn’t really pertain to the business purpose of the project.
  6. The ability to turn all this on, or off, quickly – in case it makes sense to have a configuration UI in some environments, but not others.
  7. The ability to encrypt sensitive settings, at rest, and deal with that added complexity transparently.
  8. The ability to restart the website automatically, whenever the configuration changes.
  9. The ability to work along side the existing Microsoft IConfiguration approach to configuration management, so we don’t reinvent the wheel.
  10. The ability to have one (hopefully simple) way of dealing with any application configuration, or at least a reasonable swath of configurations, from a single codebase.

To be honest, that list is a bit daunting! But, luckily, I have a few NUGET packages that can help with almost all of it. For instance, I can leverage my CG.Blazor.Plugins package to load everything as an external plugin. I can also leverage my CG.Blazor.Forms library to dynamically generate the UI screens from a single C# POCO class. I can leverage other of my NUGET packages to help with most of the other requirements, as well. A few of the items, like the role based security, might take me a bit longer, but, I still think it can all be addressed.

Let’s start by drawing a quick diagram of what I have in mind:

So, our Blazor application would load our setup library, as a plugin, at runtime. That would happen as part of the overall startup. Both the application and the setup library would share access to a private JSON file. I’m thinking we would use a private file, as opposed to sharing the configuration settings in the appSettings.json file, because, Microsoft’s configuration library, which is what typically reads the appSettings.json file, is just not intended to modify that file. We’ll need to write changes to our settings, for sure. Also, I don’t want to have to worry about possibly corrupting the appSettings.json file with our changes, so, easier all around to simply write to a private JSON file.

I think the POCO type will probably live inside the application, but it could also live in a separate assembly. I guess it depends on whatever makes the most sense. Either way, we’ll need to put a reference to the POCO type in the configuration settings, in appSettings.json, as part of the overall configuration for the plugin. That way, the setup library will know what kind of model to bind to, at runtime, for the generated UI.

The POCO class will use any number of various form generation attributes, in order to drive the generation of the UI screens. The type and placement of those attributes is up to the developer, since the form generator itself, which is used by the setup library, will happily generate HTML as long as the POCO is decorated properly.

Finally, we’ll need an alert to be raised whenever the user changes the setup, via the UI screens. Then, we’ll need some helper code, in the application, to listen for that alert and restart the host so the new changes can take affect.

The overall concept isn’t perfect, yet, but it’s enough to start prototyping with. I’ll no doubt changes some things as I go along. For now, I’m envisioning that, at the end of our journey, we’ll have a library that dynamically generates a reasonably complex UI screen for editing the setup of a Blazor website.

Next time I’ll dive further into the detailed design and start laying out my code. Until then, thanks for reading!

The source code for the CG.Blazor.Setup project is available, for free, HERE.

The CG.Blazor.Setup NUGET package is available, for free, HERE.

Photo by NASA on Unsplash