Read only if bored - TLDR - I hate f-ing spaces more than nulls.
I started my development path creating relational databases. Working with nulls was just part of the job, no complaints, I do not have an issue with them. Yes, I know that's a volatile topic, but I'm perfectly happy if you hate them; this isn't about nulls in databases.
I then became a general developer working with Microsoft technology. When I started it was relatively straightforward, VB desktop apps with a SQL Server backend or a distributed VB desktop apps with MTS or the odd intranet built with Classic ASP. I don't recall anyone moaning about nulls back then, although admittedly the internet wasn't what it is today and most developers were reading paper-based magazines or browsing MSDN CDs.
Around 2010, more and more articles began highlighting the problems nulls caused in applications. But here's the thing, in my career to date, I have spent considerably more time dealing with whitespace issues than I ever have with nulls.
I remember when SQL Server 2005 introduced, I started looking closer at user-defined functions. The very first thing I did with them was create a simple trim function I could use in table check constraints, so any varchar or nvarchar columns would have leading and trailing spaces removed, or be converted to null if the value was entirely whitespace on a nullable column. I still add trim to check constraints on every database I create. Some of you will think that's no big deal, but anyone who has spent serious time writing stored procedures and queries knows all too well how a field full of whitespace can completely destroy your report figures.
Right, enough history. On to my recent headache.
Some of you may know I am the author of the open source BlazorRamp project. What you may not know is that I also have a functional-style OSS validation library (Validated) with a companion project (Validated.Blazor) that integrates with Blazor's EditContext.
I'm currently working on the inputs for BlazorRamp and providing examples with validation, primarily using my own library but with at least one example using Data Annotations. Side note - I'm not a fan of data attributes, I tried them when they were first released but never warmed to them, so I've done my own thing ever since.
I am however a fan of regex, although you really do need to turn your brain upside down and inside out before working with them, especially once you start adding lookarounds.
In one of my examples I use a regex validator on a field, and on another I split validation so that one validator handles the allowed characters and a separate one handles length constraints. Anyway, during manual testing, which I do a lot of given my accessibility stuff, I noticed that a regex copied from another demo would correctly fail if a user typed "Paul " with a trailing space. The red error message would appear, but looking at the input control you can't see the issue unless you place the cursor in the field, and even then a single trailing space is easy to miss.
So what you may want is a regex that does what it needs to do, but doesn't fail on a trailing space, because your code can simply deal with that silently, right?.
Now some of you are thinking: "Noob, just add a normalise function in the property setter - it's even easier in C# 14 with the new field keyword, no backing field required."
set { field = NormaliseString(value); }
To those people I say: how's that going to work when you're using Blazor's oninput binding and you need to allow a space within the string value, just not after it?
This is one of those seemingly simple tasks that turns into an absolute cluster f*ck. No matter how you solve it, it's just more work, you either dirty your clean models or you end up re-validating them in your code to strip whitespace.
The solution I ended up with was adding an optional parameter to my BlazorValidationBuilder that, when set to true, mutates the string field on the model to remove leading and trailing whitespace but only during full model validation, i.e. when the form is submitted or you call validate explicitly.
For those who know my library, guessing that's approximately zero people, the BlazorValidationBuilder simply assigns validators to fields. There's no notion of mutation in the built-in validators; it's just a flag in the metadata that gets used when working with the EditContext. And just in case there is a dedicated user out there: yes, you could create a custom validator that trimmed the string, but when using the oninput option in BlazorRamp inputs or your own, it would be called on every keystroke, putting you right back to square one.
So, the point of this post: yet more days lost to whitespace. In this instance, updating, testing, and publishing a minor release of my OSS Blazor validation package just to trim a string. And I'm not done yet, I still need to update the documentation. People say nulls are bad. I say they've clearly have never spent a career at war with spaces.
Just in case you want to see what I was talking about go type stuff in the two inputs example on my BlazorRamp doc site: https://docs.blazorramp.uk/components/inputs/text-input/usage
The First name input is just a single regex that does job lot and fails with a trialing space, the Surname input will allow a single trailing space (could be more) which then gets stripped off on model validation. You can see this just be clicking the button and putting the cursor back in the input.
Break over. Back to work and then documentation, and then hopefully (please) a start on the next BlazorRamp input without whitespace issues.
Paul