<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Paul Reeder's Dump]]></title><description><![CDATA[Paul Reeder's Dump]]></description><link>https://blog.reeder.ws</link><generator>RSS for Node</generator><lastBuildDate>Fri, 15 May 2026 09:34:14 GMT</lastBuildDate><atom:link href="https://blog.reeder.ws/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Regex to the Rescue]]></title><description><![CDATA[Everyone knows that Regular Expressions can do some pretty extreme searching, but occasionally they can also be used to help you write your code.
Anyone that knows me knows that I love what I call "code that writes code". T4, Velocity, even CodeDom -...]]></description><link>https://blog.reeder.ws/regex-to-the-rescue</link><guid isPermaLink="true">https://blog.reeder.ws/regex-to-the-rescue</guid><category><![CDATA[PHP]]></category><category><![CDATA[Regex]]></category><dc:creator><![CDATA[Paul Reeder]]></dc:creator><pubDate>Mon, 24 Jul 2023 17:04:17 GMT</pubDate><content:encoded><![CDATA[<p>Everyone knows that Regular Expressions can do some pretty extreme searching, but occasionally they can also be used to help you write your code.</p>
<p>Anyone that knows me knows that I <strong><em>love</em></strong> what I call "code that writes code". T4, Velocity, even CodeDom - these are all things I just get giddy to use.</p>
<p>Occasionally, you can use RegEx to the same effect. Take, for instance, a recent feature request I was implementing to allow users to select margins in pixels or percents. Going to the browser and editing the HTML directly therein, I was able to make the changes necessary in a way that would look good to the user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690216633040/db0dca1d-403e-44f6-828f-78e228b84344.png" alt class="image--center mx-auto" /></p>
<p>The above image shows both the original (Margin Right) and the changes I wished to make (Margin Left).</p>
<p>If that was all I needed to do - change those two inputs to each have an additional dropdown, I'd have been done quickly. But it wasn't. The page has default values and then values for 10 more rules. So 22 controls in total.</p>
<p>I could have gone in and changed each of the 22 manually, but that would have been tedious, mind-numbing work, so .....</p>
<p>RegEx to the rescue...</p>
<p>The original code is PHP Volt, and one control looks like this:</p>
<pre><code class="lang-php-template"><span class="xml">
<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeft][configurationID]"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['floatDefaultMarginLeft']['configurationID'] }}"</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"floatDefaultMarginLeft"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
       <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeft][ciValue]"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['floatDefaultMarginLeft']['ciValue'] }}"</span>/&gt;</span></span>
</code></pre>
<p>I needed to change it to look like this:</p>
<pre><code class="lang-php-template"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeft][configurationID]"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['floatDefaultMarginLeft']['configurationID'] }}"</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeftType][configurationID]"</span>
       <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['floatDefaultMarginLeftType']['configurationID'] }}"</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-xs-10 col-md-8 col-lg-9"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-right:0"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"floatDefaultMarginLeft"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
               <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeft][ciValue]"</span>
               <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['floatDefaultMarginLeft']['ciValue'] }}"</span>/&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-xs-2 col-md-4 col-lg-3"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-left: 0"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[floatDefaultMarginLeftType][ciValue]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"%"</span> {% <span class="hljs-attr">if</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">floatDefaultMarginLeftType</span>']['<span class="hljs-attr">ciValue</span>'] == <span class="hljs-string">'%'</span> <span class="hljs-attr">or</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">floatDefaultMarginLeftType</span>']['<span class="hljs-attr">ciValue</span>'] <span class="hljs-attr">is</span> <span class="hljs-attr">empty</span> %} <span class="hljs-attr">selected</span> {% <span class="hljs-attr">endif</span> %}&gt;</span>%<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"px"</span> {% <span class="hljs-attr">if</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">floatDefaultMarginLeftType</span>']['<span class="hljs-attr">ciValue</span>'] == <span class="hljs-string">'px'</span> %} <span class="hljs-attr">selected</span> {% <span class="hljs-attr">endif</span> %}&gt;</span>px<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Of course, all those "MarginLeft"s are "MarginRight" for the right side. And the rules based settings are all "float1MarginLeft" or "float2MarginLeft", etc.</p>
<p>But RegEx has capturing groups, and even named capturing groups. So I ended up with this multiline RegEx:</p>
<pre><code class="lang-php-template"><span class="xml">(?<span class="hljs-tag">&lt;<span class="hljs-name">linespace</span>&gt;</span>\s*)<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"float(?&lt;num&gt;\w+)Margin(?&lt;direction&gt;\w+)"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
(?&lt;<span class="hljs-attr">linespace2</span>&gt;</span>\s*)name="ecm\[float(\w+)Margin(\w+)\]\[ciValue\]"
(?<span class="hljs-tag">&lt;<span class="hljs-name">linespace3</span>&gt;</span>\s*)value="{{ configurations\['float(\w+)Margin(\w+)'\]\['ciValue\'\] }}"\/&gt;</span>
</code></pre>
<p>And this replacement 'text':</p>
<pre><code class="lang-php-template"><span class="xml">
${linespace}<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[float${num}Margin${direction}Type][configurationID]"</span>
${<span class="hljs-attr">linespace2</span>}<span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['float${num}Margin${direction}Type']['configurationID'] }}"</span>/&gt;</span>
${linespace}<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
${linespace}    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-xs-10 col-md-8 col-lg-9"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-right:0"</span>&gt;</span>
${linespace}        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"number"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"float${num}Margin${direction}"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
${<span class="hljs-attr">linespace2</span>}        <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[float${num}Margin${direction}][ciValue]"</span>
${<span class="hljs-attr">linespace3</span>}        <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ configurations['float${num}Margin${direction}']['ciValue'] }}"</span>/&gt;</span>
${linespace}    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
${linespace}    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-xs-2 col-md-4 col-lg-3"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-left: 0"</span>&gt;</span>
${linespace}        <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ecm[float${num}Margin${direction}Type][ciValue]"</span>&gt;</span>
${linespace}            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"%"</span> {% <span class="hljs-attr">if</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">float</span>${<span class="hljs-attr">num</span>}<span class="hljs-attr">Margin</span>${<span class="hljs-attr">direction</span>}<span class="hljs-attr">Type</span>']['<span class="hljs-attr">ciValue</span>'] == <span class="hljs-string">'%'</span> <span class="hljs-attr">or</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">float</span>${<span class="hljs-attr">num</span>}<span class="hljs-attr">Margin</span>${<span class="hljs-attr">direction</span>}<span class="hljs-attr">Type</span>']['<span class="hljs-attr">ciValue</span>'] <span class="hljs-attr">is</span> <span class="hljs-attr">empty</span> %} <span class="hljs-attr">selected</span> {% <span class="hljs-attr">endif</span> %}&gt;</span>%<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
${linespace}            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"px"</span> {% <span class="hljs-attr">if</span> <span class="hljs-attr">configurations</span>['<span class="hljs-attr">float</span>${<span class="hljs-attr">num</span>}<span class="hljs-attr">Margin</span>${<span class="hljs-attr">direction</span>}<span class="hljs-attr">Type</span>']['<span class="hljs-attr">ciValue</span>'] == <span class="hljs-string">'px'</span> %} <span class="hljs-attr">selected</span> {% <span class="hljs-attr">endif</span> %}&gt;</span>px<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
${linespace}        <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
${linespace}    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
${linespace}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>And voila, 22 changes complete!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690218123912/d10c5567-0218-4ebb-aeac-3b98878d80c9.png" alt class="image--center mx-auto" /></p>
<p>So ... use the tools you have at your disposal. Work smart, not hard. And get a good RegEx tool. On Windows 10/11, I recommend Regex Hero, with SkyD Regex a close second.</p>
]]></content:encoded></item><item><title><![CDATA[ASP.NET Primer]]></title><description><![CDATA[This blog entry is for those of you who are programmers, but haven't done a lot a of ASP.NET programming, or not much in the .NET Core era. It is easy to feel overwhelmed by the framework, just wanting to write some code, but not understanding how to...]]></description><link>https://blog.reeder.ws/aspnet-primer</link><guid isPermaLink="true">https://blog.reeder.ws/aspnet-primer</guid><category><![CDATA[C#]]></category><category><![CDATA[ASP.NET]]></category><dc:creator><![CDATA[Paul Reeder]]></dc:creator><pubDate>Wed, 19 Jul 2023 20:29:02 GMT</pubDate><content:encoded><![CDATA[<p>This blog entry is for those of you who are programmers, but haven't done a lot a of ASP.NET programming, or not much in the .NET Core era. It is easy to feel overwhelmed by the framework, just wanting to write some code, but not understanding how to write code in the confines and benefits the framework provides.</p>
<p>First, it is important to note the following things about ASP.NET:</p>
<ol>
<li><p>It is heavily dependent upon Dependency Injection</p>
</li>
<li><p>Middleware is daunting, but it is powerful</p>
</li>
<li><p>Folder structures are well-defined and mandatory (mostly)</p>
</li>
</ol>
<h1 id="heading-dependency-injection">Dependency Injection</h1>
<p>First, let's talk about DI. Are you writing a controller and need resources outside your controller, like the application's configuration, a database context instance, and a logging instance? No problem, just put them in your constructor and DI will supply them when your controller is instantiated.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> MyContext _db;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span> _someSetting;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> ILogger&lt;MyController&gt; _logger;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyController</span>(<span class="hljs-params">MyContext db, IConfiguration config, ILogger&lt;MyController&gt; logger</span>)</span>
{
    _db = db;
    _logger = logger;
    _someSetting = config[<span class="hljs-string">"App:SomeSetting"</span>];
}
</code></pre>
<p>Building a class to provide common functionality Application wide? Then you should consider building a service so that it can be injected via DI.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">IClock</span>
{
    <span class="hljs-function">DateTime <span class="hljs-title">GetTime</span>(<span class="hljs-params"></span>)</span>;
    <span class="hljs-function">DateTime <span class="hljs-title">GetTimeUtc</span>(<span class="hljs-params"></span>)</span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">OffsetClock</span>: <span class="hljs-title">IClock</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> ILogger&lt;OffsetClock&gt; _logger;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> TimeSpan _offset;

    <span class="hljs-function"><span class="hljs-keyword">public</span> class <span class="hljs-title">OffsetClock</span>(<span class="hljs-params">ILogger&lt;OffsetClock&gt; logger, IConfiguration config</span>)</span>
    {
        _logger = logger;
        _offset = TimeSpan.Parse(config[<span class="hljs-string">"Clock:Offset"</span>]);
        _logger.LogDebug(<span class="hljs-string">"Offset clock instantiated with offset: {Offset}"</span>, _offset);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> DateTime <span class="hljs-title">GetTime</span>(<span class="hljs-params"></span>)</span>
    {
        _logger.LogDebug(<span class="hljs-string">"Getting time"</span>);
        <span class="hljs-keyword">return</span> DateTime.Now.Add(_offset);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> DateTime <span class="hljs-title">GetTimeUtc</span>(<span class="hljs-params"></span>)</span>
    {
        _logger.LogDebug(<span class="hljs-string">"Getting time in UTC"</span>);
        <span class="hljs-keyword">return</span> DateTime.UtcNow.Add(_offset);
    }
}
</code></pre>
<p>Notice that the above example contained both an implementation class (OffsetClock) and interface (IClock). The implementation class uses other classes which themselves are supplied to the constructor via DI.</p>
<p>Now that you have a service, you need to tell DI about your service. But before you do, you should consider the lifetime of your shiny new service. Is each method call independent of each other? Then perhaps you want your new service to be a Singleton service. Should a single instance of your service be used by everything which needs it when all working for the same HTTP request, or other unit of work? Then you might consider a Scoped service. And finally if a new instance should be created every single time it is needed, then you need a Transient service.</p>
<p>Setting up your service is done when building the ASP.NET WebApplication, typically in Program.cs. WebApplicationBuilder.Services is the service collection where you can add services. There are a lot of different ways to do so, but let's look at just three for now:</p>
<ul>
<li><p>AddTransient&lt;T,U&gt;() - Adds a transient service</p>
</li>
<li><p>AddScoped&lt;T,U&gt;() - Adds a scoped service</p>
</li>
<li><p>AddSingleton&lt;T,U&gt;() - Adds a singleton service</p>
</li>
</ul>
<p>Looking back at our OffsetClock, it could easily be a singleton service since it doesn't maintain any pertinent information between calls.</p>
<pre><code class="lang-csharp">builder.AddSingleton&lt;IClock, OffsetClock&gt;();
</code></pre>
<p>Now, the first time a component needs an IClock instance, an OffsetClock instance will be created. Every time after that when a component needs an IClock instance, this same instance of OffsetClock will be provided.</p>
<h1 id="heading-middeware">Middeware</h1>
<p>The ASP.NET Middleware pipeline is amazing. It truly is. But it is dangerous, too. I wish I had understood it like I understand it now when I first started writing ASP.NET Core applications back in the ASP.NET Core 2.1 days. You wouldn't believe the spaghetti I wrote because I just couldn't make the middleware do what I wanted it to do.</p>
<p>Everything under the sun will show you the diagram of Middleware #1 passing the request to Middleware #2 which passes the request to Middleware #3, which completes the request. Then Middleware #3 passes the response to Middleware #2 which passes the response to Middleware #1 before returning the response back to the client.</p>
<p>But here's the important thing, and it is simple, but IMPORTANT. Honestly, I don't know why everywhere you see that middleware diagram you don't also see this statement. The ORDER of adding middleware to the pipeline when building the WebApplication defines the ORDER of the execution of the middleware.</p>
<p>So if you have an application which already had Authentication via app.UseAuthentication() and now want to add roles for users and thus add Authorization functionality via app.UseAuthorization(), then it is very important that you place the call to app.UserAuthorization() AFTER the call to app.UseAuthentication(). After all, if you try to authorize something before you know who the user is via authentications, well that won't work, will it?</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Honestly, that is a very good example. I know a web app out in the wild right now where with methods like "IsInRole(...)" and "IsAllowed(...)". Yep, I know it because I wrote it. Oh, I hope I don't have to do maintenance on it any time soon!</div>
</div>

<p>Anyway, middleware is important. It is powerful. Want to add logging of raw POST data and raw responses? Middleware could do that for you. Want to make use of more functionality provided by ASP.NET, such as adding MVC controllers to Razor Pages? It can do that too. But be mindful of the ordering - it is critically important.</p>
<h1 id="heading-folder-structures">Folder Structures</h1>
<p>Many folders are mandated by ASP.NET out of the box, such as:</p>
<ul>
<li><p>/wwwroot contains static files which are served directly</p>
</li>
<li><p>/Controllers contains controllers</p>
</li>
<li><p>/Views contains MVC views</p>
</li>
<li><p>/Pages contains Razor Pages (which I highly recommend using whenever able)</p>
</li>
<li><p>/Areas contains trees of Razor Pages and MVC Views located under a subfolder which equates to an HTTP path folder</p>
</li>
</ul>
<p>I strongly suggest adopting these other root folders as well:</p>
<ul>
<li><p>/Model contains model classes, possibly in a tree when there are multiple model sets (e.g. One for a database, one for API DTOs, etc.)</p>
</li>
<li><p>/Middleware contains middleware classes, or classes used by generic middleware</p>
</li>
<li><p>/Services contains DI services</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>