<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andy Boot</title>
    <description>The latest articles on Forem by Andy Boot (@andy_boot).</description>
    <link>https://forem.com/andy_boot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F729113%2Ff16c1b9e-1596-4ec0-a6ca-37144e402f1e.jpg</url>
      <title>Forem: Andy Boot</title>
      <link>https://forem.com/andy_boot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andy_boot"/>
    <language>en</language>
    <item>
      <title>Umbraco 13 - Setting The Backoffice Login Background &amp; Logo From Content Data</title>
      <dc:creator>Andy Boot</dc:creator>
      <pubDate>Wed, 15 May 2024 16:16:47 +0000</pubDate>
      <link>https://forem.com/andy_boot/umbraco-13-setting-the-backoffice-login-background-logo-from-content-data-k35</link>
      <guid>https://forem.com/andy_boot/umbraco-13-setting-the-backoffice-login-background-logo-from-content-data-k35</guid>
      <description>&lt;p&gt;The release of Umbraco 13 back in December 2023 brought with it a whole new look and refreshed login screen based on the same technology as "Bellissima" (the upcoming Umbraco 14 backoffice revamp).&lt;/p&gt;

&lt;p&gt;Out of the box, it looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp68lkj5xvxtx63xla8vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp68lkj5xvxtx63xla8vn.png" alt="Umbraco 13 login screen"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Umbraco offers a way to customise the logo and image by setting alternative values against the &lt;code&gt;Umbraco:CMS:Content:LoginBackgroundImage&lt;/code&gt; and &lt;code&gt;Umbraco:CMS:Content:LoginLogoImage&lt;/code&gt; properties within &lt;code&gt;appsettings.json&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvd9oznnb08xbs844usp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvd9oznnb08xbs844usp1.png" alt="appsettings.json showing example LoginBackgroundImage and LoginLogoImage values"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out &lt;strong&gt;Warren Buckley&lt;/strong&gt;'s blog post here for a further breakdown of how this works: &lt;a href="https://blog.hackmakedo.com/2023/11/20/quick-tip-how-to-customise-your-umbraco-13-login-screen/" rel="noopener noreferrer"&gt;https://blog.hackmakedo.com/2023/11/20/quick-tip-how-to-customise-your-umbraco-13-login-screen/&lt;/a&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After watching a recent video uploaded by &lt;strong&gt;Paul Seal&lt;/strong&gt;, it inspired me to expand on the idea he presented. Paul demo's how to achieve a similar desired effect by providing an element of customisability from the Umbraco backoffice by utilising the Umbraco package Skybrud Redirects. Check it out here:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nhlGtP3QSjE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  My approach
&lt;/h2&gt;

&lt;p&gt;Using a similar methodology to Paul's approach, I'm going to show you how to do a code only implementation, without the need for an additional package dependency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before I begin, I structure my content tree so that the root page holds all the global settings for the website. Some developers prefer to have a separate settings document type held as a child node (which is also perfectly acceptable). If this is you, you'll need to adapt parts of the code below around your setup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, we're going to create two new properties against the root document type:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Name:&lt;/em&gt;&lt;/strong&gt; Umbraco Custom Login Background Image&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Alias:&lt;/em&gt;&lt;/strong&gt; umbracoCustomLoginBackground&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Description:&lt;/em&gt;&lt;/strong&gt; Suggested image size: 936x1404 pixels (JPG)&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Data type:&lt;/em&gt;&lt;/strong&gt; Media Picker&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Name:&lt;/em&gt;&lt;/strong&gt; Umbraco Custom Login Logo Image&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Alias:&lt;/em&gt;&lt;/strong&gt; umbracoCustomLoginLogo&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Description:&lt;/em&gt;&lt;/strong&gt; Suggested image size: 300x82 pixels (SVG or PNG)&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Data type:&lt;/em&gt;&lt;/strong&gt; Media Picker&lt;/p&gt;

&lt;p&gt;Like so:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fettxdgfmia6keiz6p03z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fettxdgfmia6keiz6p03z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we're going to populate our new fields with some appropriate images from the media library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7ngovpn46j899dmq13w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7ngovpn46j899dmq13w.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we just need to wire this up with a small piece of middleware:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UmbracoLoginImageMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRuntimeState&lt;/span&gt; &lt;span class="n"&gt;_runtimeState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUmbracoContextFactory&lt;/span&gt; &lt;span class="n"&gt;_umbracoContextFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_BACKGROUND_IMAGE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/umbraco/assets/img/login.jpg"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_LOGO_IMAGE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/umbraco/assets/img/application/umbraco_logo_blue.svg"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LOGIN_BACKGROUND_IMAGE_PROPERTY_ALIAS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"umbracoCustomLoginBackground"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LOGIN_LOGO_IMAGE_PROPERTY_ALIAS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"umbracoCustomLoginLogo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UmbracoLoginImageMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RequestDelegate&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IRuntimeState&lt;/span&gt; &lt;span class="n"&gt;runtimeState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IUmbracoContextFactory&lt;/span&gt; &lt;span class="n"&gt;umbracoContextFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_runtimeState&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runtimeState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_umbracoContextFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;umbracoContextFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_runtimeState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Level&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;RuntimeLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pathAndQuery&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEncodedPathAndQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathAndQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvariantIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_BACKGROUND_IMAGE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;pathAndQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvariantIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_LOGO_IMAGE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Handle the background or logo image&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="nf"&gt;HandleLoginImageRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_BACKGROUND_IMAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOGIN_BACKGROUND_IMAGE_PROPERTY_ALIAS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
            &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;HandleLoginImageRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_UMBRACO_LOGIN_LOGO_IMAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOGIN_LOGO_IMAGE_PROPERTY_ALIAS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;HandleLoginImageRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;defaultImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;propertyAlias&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// If the current request URL equals the default path or what we have in appsettings.json&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;InvariantEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defaultImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_umbracoContextFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureUmbracoContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;contentAtRoot&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UmbracoContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;GetAtRoot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Get all document nodes at the root level of our content&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstRootContent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contentAtRoot&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Get the first one (adjust this if you want to pull through something specific)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstRootContent&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;firstRootContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propertyAlias&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// If our sites root page has a matching property with a value&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mediaItemUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;firstRootContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPublishedContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;propertyAlias&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Get &amp;amp; parse the media library item to get the direct URL&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mediaItemUrl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mediaItemUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Redirect to the media set in the backoffice&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, we just need to register it from within a composer:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComposer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IComposer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Compose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUmbracoBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UmbracoPipelineOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UmbracoPipelineFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"UmbracoLoginImageMiddleware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;applicationBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;applicationBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UmbracoLoginImageMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;applicationBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;applicationBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Drumroll...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6h7hdzhn86ekrzg1mua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6h7hdzhn86ekrzg1mua.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The middleware finds the first root page and attempts to get values from the two newly created media picker properties. If the either of the two image HTTP request matches either of the default image URL's and the adjacent property has a value then it'll perform a permanent 301 redirect to your media library image instead.&lt;/p&gt;

&lt;p&gt;While we redirect the background image from &lt;code&gt;/umbraco/assets/img/login.jpg&lt;/code&gt;, it's probably a safe bet that this wouldn't harm any other component or page within the backoffice. However, overriding &lt;code&gt;/umbraco/assets/img/application/umbraco_logo_blue.svg&lt;/code&gt; gives me a little more concern as it may be used elsewhere. On initial inspection I can't see anywhere specific where this is also defined so we may be able to get away with it. If however it does reveal itself to be used for other things we can workaround this by re-saving the SVG to somewhere within your &lt;code&gt;wwwroot&lt;/code&gt; folder, setting the &lt;code&gt;Umbraco:CMS:Content:LoginLogoImage&lt;/code&gt; value and updating the &lt;code&gt;DEFAULT_UMBRACO_LOGIN_LOGO_IMAGE&lt;/code&gt; const within the middleware.&lt;/p&gt;

&lt;p&gt;Please be aware that frequent changing of redirects against a URL may result in the redirect being cached and therefore you won't always see your changes immediately. To overcome this, disable browser caching.&lt;/p&gt;

&lt;p&gt;I hope you find this article interesting. I wanted to share this approach with you because I hadn't seen it done yet.&lt;/p&gt;

&lt;p&gt;Thanks for reading,&lt;br&gt;
Andy&lt;br&gt;
👋&lt;/p&gt;

</description>
      <category>umbraco</category>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deep Dive Into Umbraco String Extension Methods</title>
      <dc:creator>Andy Boot</dc:creator>
      <pubDate>Sat, 08 Apr 2023 08:21:54 +0000</pubDate>
      <link>https://forem.com/andy_boot/deep-dive-into-umbraco-string-extension-methods-4ee2</link>
      <guid>https://forem.com/andy_boot/deep-dive-into-umbraco-string-extension-methods-4ee2</guid>
      <description>&lt;p&gt;&lt;em&gt;‟&lt;strong&gt;Let's talk about ex-tension methods, baby!&lt;/strong&gt;”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Extension methods are a powerful feature of C# that allows developers to add new methods to existing types without the need for inheritance, modification or recompilation of the original class. Fortunately, the .Net family of frameworks provides numerous built-in extension methods, but with Umbraco you get an additional set of methods that can help you keep your code concise, readable, and aligned with the DRY principle.&lt;/p&gt;

&lt;p&gt;By chance, I stumbled upon this collection of extensions a while back when intellisense suggested &lt;code&gt;IsNullOrWhiteSpace()&lt;/code&gt; and &lt;code&gt;StripHtml()&lt;/code&gt; to me. Knowing that these were not part of the vanilla .Net, I hit F12 &lt;em&gt;(go to definition)&lt;/em&gt; and discovered a treasure trove of other extension methods. In this article, we will explore the plethora of string extension methods that Umbraco CMS offers and how to utilise them.&lt;/p&gt;

&lt;p&gt;Please note that the information below pertains to Umbraco version 11.0, although some features may also be relevant to older and newer versions. These methods are found in the &lt;code&gt;StringExtensions&lt;/code&gt; class within the &lt;code&gt;Umbraco.Extensions&lt;/code&gt; namespace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of contents&lt;/strong&gt;&lt;br&gt;
⭐ = My Favourite&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
GetIdsFromPathReversed() - Returns the IDs of the items in a path in reverse order.&lt;/li&gt;
&lt;li&gt;
StripWhitespace() - Removes whitespace characters from the beginning and end of a string.&lt;/li&gt;
&lt;li&gt;
StripFileExtension() - Removes the file extension from a file path.&lt;/li&gt;
&lt;li&gt;
GetFileExtension() - Returns the file extension of a file path.&lt;/li&gt;
&lt;li&gt;
DetectIsJson() - Determines if a string is a valid JSON object.&lt;/li&gt;
&lt;li&gt;
DetectIsEmptyJson() - Determines if a string is an empty JSON object.&lt;/li&gt;
&lt;li&gt;⭐ReplaceNonAlphanumericChars() - Replaces all non-alphanumeric characters in a string with a specified replacement.&lt;/li&gt;
&lt;li&gt;
CleanForXss() - Sanitizes a string to remove potential cross-site scripting (XSS) vulnerabilities.&lt;/li&gt;
&lt;li&gt;
ExceptChars() - Returns a string with all instances of specified characters removed.&lt;/li&gt;
&lt;li&gt;
GenerateStreamFromString() - Creates a stream from a string.&lt;/li&gt;
&lt;li&gt;⭐AppendQueryStringToUrl() - Appends a query string to a URL.&lt;/li&gt;
&lt;li&gt;
MakePluralName() - Returns the plural form of a noun.&lt;/li&gt;
&lt;li&gt;
IsVowel() - Determines if a character is a vowel.&lt;/li&gt;
&lt;li&gt;
Trim() - Removes whitespace characters from the beginning and end of a string.&lt;/li&gt;
&lt;li&gt;
EncodeJsString() - Encodes a string to be used in a JavaScript string literal.&lt;/li&gt;
&lt;li&gt;
EnsureStartsWith() - Ensures that a string starts with a specified prefix.&lt;/li&gt;
&lt;li&gt;
EnsureEndsWith() - Ensures that a string ends with a specified suffix.&lt;/li&gt;
&lt;li&gt;
IsLowerCase() - Determines if a string is all lowercase.&lt;/li&gt;
&lt;li&gt;
IsUpperCase() - Determines if a string is all uppercase.&lt;/li&gt;
&lt;li&gt;⭐IsNullOrWhiteSpace() - Determines if a string is null or consists only of whitespace characters.&lt;/li&gt;
&lt;li&gt;
IfNullOrWhiteSpace() - Returns a default value if a string is null or consists only of whitespace characters.&lt;/li&gt;
&lt;li&gt;⭐ToDelimitedList() - Converts a list of strings to a delimited string.&lt;/li&gt;
&lt;li&gt;
EnumTryParse() - Provides a safer way to parse a string value to a specified enum type.&lt;/li&gt;
&lt;li&gt;
EnumParse() - Provides an easy way to parse a string value to a specified enum type.&lt;/li&gt;
&lt;li&gt;⭐StripHtml() - Removes HTML tags from a string.&lt;/li&gt;
&lt;li&gt;
EncodeAsGuid() - Encodes a GUID as a string.&lt;/li&gt;
&lt;li&gt;
ConvertToHex() - Converts a byte array to a hexadecimal string.&lt;/li&gt;
&lt;li&gt;
DecodeFromHex() - Converts a hexadecimal string to a byte array.&lt;/li&gt;
&lt;li&gt;
ToUrlBase64() - Converts a byte array to a URL-safe base64-encoded string.&lt;/li&gt;
&lt;li&gt;
FromUrlBase64() - Decodes a URL-safe Base64 string into its original string representation.&lt;/li&gt;
&lt;li&gt;
InvariantFormat() - Formats a string with invariant culture.&lt;/li&gt;
&lt;li&gt;
ToInvariantString() - Converts an integer or long value to its invariant string representation.&lt;/li&gt;
&lt;li&gt;⭐InvariantEquals() - Compares two strings in a case-insensitive manner and with invariant culture.&lt;/li&gt;
&lt;li&gt;⭐InvariantStartsWith() - Checks if a string starts with a specific substring in a case-insensitive manner using the InvariantCultureIgnoreCase option.&lt;/li&gt;
&lt;li&gt;
InvariantEndsWith() - Checks if a string ends with a specific substring in a case-insensitive manner using the InvariantCultureIgnoreCase option.&lt;/li&gt;
&lt;li&gt;⭐InvariantContains() - Checks if a string or IEnumerable of strings contains a specific substring in a case-insensitive manner.&lt;/li&gt;
&lt;li&gt;⭐InvariantIndexOf() - Finds the index of the first occurrence of a specific substring in a string in a case-insensitive manner using the OrdinalIgnoreCase option.&lt;/li&gt;
&lt;li&gt;
InvariantLastIndexOf() - Finds the index of the last occurrence of a specific substring in a string in a case-insensitive manner using the OrdinalIgnoreCase option.&lt;/li&gt;
&lt;li&gt;
ParseInto() - Attempts to parse a string into the supplied type by finding and using the Type's "Parse" method.&lt;/li&gt;
&lt;li&gt;
GenerateHash() - Generates a hash of a string using a specified hash algorithm.&lt;/li&gt;
&lt;li&gt;
ToSHA1() - Converts a string to its SHA1 hash value.&lt;/li&gt;
&lt;li&gt;
UrlTokenDecode() - Decodes a string that was encoded with UrlTokenEncode.&lt;/li&gt;
&lt;li&gt;
UrlTokenEncode() - Encodes a byte array for use in URLs, files, or other places where a string is required.&lt;/li&gt;
&lt;li&gt;
NormaliseDirectoryPath() - Ensures a given directory path ends with a directory separator character.&lt;/li&gt;
&lt;li&gt;⭐Truncate() - Truncates a given string to a specified length and appends a suffix at the end of it.&lt;/li&gt;
&lt;li&gt;
StripNewLines() - Removes carriage returns and line feeds from a given string.&lt;/li&gt;
&lt;li&gt;
ToSingleLine() - Converts a multiline string to a single line by replacing line breaks with spaces.&lt;/li&gt;
&lt;li&gt;
OrIfNullOrWhiteSpace() - Returns the input string if it is not null or whitespace, otherwise, it returns the alternative string.&lt;/li&gt;
&lt;li&gt;
ToFirstUpper() - Converts the first character of a string to uppercase.&lt;/li&gt;
&lt;li&gt;
ToFirstLower() - Converts the first character of a string to lowercase.&lt;/li&gt;
&lt;li&gt;
ToFirstUpperInvariant() / ToFirstLowerInvariant() - Similar to &lt;code&gt;ToFirstUpper()&lt;/code&gt; and &lt;code&gt;ToFirstLower()&lt;/code&gt;, respectively, but they use the casing rules of the invariant culture.&lt;/li&gt;
&lt;li&gt;
ReplaceMany() - Replaces multiple occurrences of a set of characters or strings in a given string with a specified replacement character or string.&lt;/li&gt;
&lt;li&gt;
ReplaceFirst() - A method that returns a new string in which only the first occurrence of a specified string is replaced by a specified replacement string.&lt;/li&gt;
&lt;li&gt;
Replace() - A method that returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string. &lt;/li&gt;
&lt;li&gt;
ToCSharpString() - A method that converts a literal string into a C# expression.&lt;/li&gt;
&lt;li&gt;
EscapeRegexSpecialCharacters() - A method that escapes all the special characters used in a regular expression.&lt;/li&gt;
&lt;li&gt;
ContainsAny() - A method that returns a boolean if any of the strings in the list of strings exists within the source string.&lt;/li&gt;
&lt;li&gt;
CsvContains() - Checks if a comma-separated string (CSV) contains a given value.&lt;/li&gt;
&lt;li&gt;⭐ToFriendlyName() - Converts a file name to a user-friendly name for a content item.&lt;/li&gt;
&lt;li&gt;
ToValidXmlString() - Replaces all invalid Unicode characters in a string for XML files.&lt;/li&gt;
&lt;li&gt;
ToGuid() - Converts a string to a GUID (Globally Unique Identifier).&lt;/li&gt;
&lt;li&gt;
NullOrWhiteSpaceAsNull() - Turns a null-or-whitespace string into a null string.&lt;/li&gt;
&lt;li&gt;
IsFullPath() - Checks whether a given path is a full path including drive letter.&lt;/li&gt;
&lt;li&gt;⭐ToSafeAlias() - Cleans a string to produce a string that can be safely used in an alias.&lt;/li&gt;
&lt;li&gt;
ToUrlSegment() - Cleans a string to produce a string that can safely be used in an URL segment.&lt;/li&gt;
&lt;li&gt;⭐ToCleanString() - Cleans a string by removing any unwanted characters and formatting it according to the provided options.&lt;/li&gt;
&lt;li&gt;
SplitPascalCasing() - Splits a Pascal-cased string into a phrase separated by spaces.&lt;/li&gt;
&lt;li&gt;
ToSafeFileName() - Cleans a string to produce a safe filename for use internally (on disk) or externally (as a URL).&lt;/li&gt;
&lt;li&gt;
EscapedSplit() - Splits a string with an escape character that allows for the split character to exist within the string.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  GetIdsFromPathReversed()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string path&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;GetIdsFromPathReversed()&lt;/code&gt; extension method takes a string path and returns an array of integers that represent node ids in reverse order, from deepest to shallowest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string path = "1,2,3";
int[] nodeIds = path.GetIdsFromPathReversed();
// nodeIds: [3, 2, 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  StripWhitespace()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string txt&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;StripWhitespace()&lt;/code&gt; extension method removes all new line and tab characters from a string. This method uses the Regex.Replace() method to replace any whitespace characters with an empty string. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "Some text \n with \t whitespace";
string stripped = text.StripWhitespace();
// stripped: "Sometextwithwhitespace"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  StripFileExtension()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string fileName&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;StripFileExtension()&lt;/code&gt; extension method removes the file extension from a filename. This method checks if the filename contains any new line characters, and returns the original filename if it does. If the filename contains a file extension, it removes it using the Substring() method and returns the result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string filename = "example.txt";
string stripped = filename.StripFileExtension();
// stripped: "example"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  GetFileExtension()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string file&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;GetFileExtension()&lt;/code&gt; extension method returns the file extension of a path or URL. This method uses a regular expression to match the last occurrence of a dot character before the start of a query string or the end of the string. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string path = "example.txt";
string extension = path.GetFileExtension();
// extension: ".txt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  DetectIsJson()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;DetectIsJson()&lt;/code&gt; extension method checks if a string is a valid JSON string. This method trims the input string and checks if it starts with { and ends with } or starts with [ and ends with ]. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string json = "{\"name\":\"John\"}";
bool isJson = json.DetectIsJson();
// isJson: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  DetectIsEmptyJson()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;DetectIsEmptyJson()&lt;/code&gt; extension method checks if a string is an empty JSON array or object. This method replaces all whitespace characters with an empty string using a regular expression, and then checks if the resulting string is equal to [] or {}. &lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string json = "   {}   ";
bool isEmptyJson = json.DetectIsEmptyJson();
// isEmptyJson: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ReplaceNonAlphanumericChars()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input, char replacement&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ReplaceNonAlphanumericChars()&lt;/code&gt; extension method replaces any non-alphanumeric characters in a string with a specified replacement string or character.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var input = "This is a string with some non-alphanumeric characters: $100, @username";
var replacedString = input.ReplaceNonAlphanumericChars("-");
// replacedString: "This-is-a-string-with-some-non-alphanumeric-characters--100---username"

var replacedChar = input.ReplaceNonAlphanumericChars('_');
// replacedChar: "This_is_a_string_with_some_non_alphanumeric_characters__100___username"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CleanForXss()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input, params char[] ignoreFromClean&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;CleanForXss()&lt;/code&gt; extension method helps prevent cross-site scripting (XSS) attacks by stripping out potentially harmful characters from a string. It uses the StripHtml method to remove any HTML tags from the string, then removes any characters listed in a predefined list (CleanForXssChars). You can optionally specify additional characters to ignore by passing them as arguments to the method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string userInput = "&amp;lt;script&amp;gt;alert('XSS!');&amp;lt;/script&amp;gt;";
string sanitizedInput = userInput.CleanForXss();

// sanitizedInput: "alert('XSS!');"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ExceptChars()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string str, HashSet&amp;lt;char&amp;gt; toExclude&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ExceptChars()&lt;/code&gt; extension method removes all characters in a string that match a set of specified characters. It takes a HashSet as input, which contains the characters to exclude.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
HashSet&amp;lt;char&amp;gt; excludedChars = new HashSet&amp;lt;char&amp;gt;(new[] { 'o', 'l' });
string output = input.ExceptChars(excludedChars);

// output: "He, wrd!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  GenerateStreamFromString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string s&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;GenerateStreamFromString()&lt;/code&gt; extension method converts a string into a stream object, which can be useful when working with streams in .NET.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
Stream stream = input.GenerateStreamFromString();
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
var output = Encoding.UTF8.GetString(buffer);

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  AppendQueryStringToUrl()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string url, params string[] queryStrings&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;AppendQueryStringToUrl()&lt;/code&gt; extension method appends a set of query string parameters to a URL. It ensures that the resulting URL is structured correctly, with only one '?' character and proper delimiters between parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string url = "https://example.com";
string queryString = "foo=bar&amp;amp;baz=qux";
string result = url.AppendQueryStringToUrl(queryString);

// result: "https://example.com?foo=bar&amp;amp;baz=qux"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MakePluralName()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string name&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;MakePluralName()&lt;/code&gt; extension method pluralizes a singular noun. It's a fun little extension method that uses a set of simple rules to convert a word into its plural form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string singular = "apple";
string plural = singular.MakePluralName();

// plural: "apples"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IsVowel()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this char c&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IsVowel()&lt;/code&gt; extension method checks whether a character is a vowel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char c = 'a';
bool isVowel = c.IsVowel();

// isVowel: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Trim()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string value, string forRemoving&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Trim()&lt;/code&gt; extension method trims a string using another string as the trim value. It works similarly to the built-in Trim method, but allows you to specify a string rather than a single character.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
string trimValue = "Hdlr!";
string output = input.Trim(trimValue);

// output: ", wor"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EncodeJsString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string s&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EncodeJsString()&lt;/code&gt; extension method encodes a string for use in JavaScript code. It replaces certain special characters with their escape codes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, \"world\"!";
string output = input.EncodeJsString();

// output: "Hello, \\\"world\\\"!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EnsureStartsWith()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input, string toStartWith&lt;/code&gt;, &lt;code&gt;this string input, char value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EnsureStartsWith()&lt;/code&gt; extension method ensures that a string starts with a specified character or string. If the input string already starts with the specified character or string, the original string is returned. If not, the specified character or string is prepended to the input string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "world!";
string output = input.EnsureStartsWith("Hello, ");

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EnsureEndsWith()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input, string toEndWith&lt;/code&gt;, &lt;code&gt;this string input, char value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EnsureEndsWith()&lt;/code&gt; extension method ensures that a string ends with a specified character or string. If the input string already ends with the specified character or string, the original string is returned. If not, the specified character or string is appended to the input string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello,";
string output = input.EnsureEndsWith(" world!");

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IsLowerCase()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this char ch&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IsLowerCase()&lt;/code&gt; extension method checks whether a character is a lowercase letter or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char ch = 'a';
bool isLower = ch.IsLowerCase(); 
// isLower: True

char ch2 = 'A';
bool isNotLower = ch2.IsLowerCase(); 
// isNotLower: False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IsUpperCase()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this char ch&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IsUpperCase()&lt;/code&gt; extension method checks whether a character is an uppercase letter or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char ch = 'A';
bool isUpper = ch.IsUpperCase(); 
// isUpper: True

char ch2 = 'a';
bool isNotUpper = ch2.IsUpperCase(); 
// isNotUpper: False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IsNullOrWhiteSpace()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string? value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IsNullOrWhiteSpace()&lt;/code&gt; extension method checks whether a string is null, empty, or consists only of white-space characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "   ";
bool isNullOrWhiteSpace = input.IsNullOrWhiteSpace(); 
// isNullOrWhiteSpace: True

string input2 = " Hello ";
bool isNotNullOrWhiteSpace = input2.IsNullOrWhiteSpace(); 
// isNotNullOrWhiteSpace: False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IfNullOrWhiteSpace()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string? str, string? defaultValue&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IfNullOrWhiteSpace()&lt;/code&gt; extension method checks whether a string is null, empty, or consists only of white-space characters. If it is, it returns the default value provided; otherwise, it returns the input string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = null;
string output = input.IfNullOrWhiteSpace("Hello, world!");

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToDelimitedList()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string list, string delimiter = ","&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToDelimitedList()&lt;/code&gt; extension method converts a string containing a delimited list of items into an IList. By default, the delimiter is a comma (","), but a different delimiter can be specified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "one, two, three";
IList&amp;lt;string&amp;gt; output = input.ToDelimitedList();

// output: [ "one", "two", "three" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EnumTryParse()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string strType, bool ignoreCase, out T? result&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The EnumTryParse() extension method provides a safer way to parse a string value to a specified enum type. This method takes three parameters: the first parameter &lt;code&gt;strType&lt;/code&gt; is the string value that needs to be converted to the specified enum type, the second parameter &lt;code&gt;ignoreCase&lt;/code&gt; is a bool value that specifies whether the conversion should be case-insensitive, and the third parameter &lt;code&gt;result&lt;/code&gt; is an out parameter that holds the converted value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string strValue = "Red";
bool success = strValue.EnumTryParse&amp;lt;Color&amp;gt;(true, out Color color); // Case-insensitive conversion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we are converting a string value "Red" to a Color enum value. The second parameter true specifies that the conversion should be case-insensitive. If the conversion is not possible, this method will set the result parameter to null and return false. Otherwise, it will set the result parameter to the converted value and return true.&lt;/p&gt;




&lt;h2&gt;
  
  
  EnumParse()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string strType, bool ignoreCase&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EnumParse&amp;lt;T&amp;gt;()&lt;/code&gt; extension method provides an easy way to parse a string value to a specified enum type. This method takes two parameters: the first parameter strType is the string value that needs to be converted to the specified enum type, and the second parameter ignoreCase is a bool value that specifies whether the conversion should be case-insensitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string strValue = "Red";
Color color = strValue.EnumParse&amp;lt;Color&amp;gt;(true); // Case-insensitive conversion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we are converting a string value "Red" to a Color enum value. The second parameter true specifies that the conversion should be case-insensitive. If the conversion is not possible, this method will throw an exception.&lt;/p&gt;




&lt;h2&gt;
  
  
  StripHtml()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;StripHtml()&lt;/code&gt; extension method removes all HTML tags from a string. It is helpful when a user's input is in HTML format and needs to be displayed without HTML tags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "&amp;lt;p&amp;gt;Hello &amp;lt;b&amp;gt;world!&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;";
string output = input.StripHtml();

// output: "Hello world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EncodeAsGuid()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EncodeAsGuid()&lt;/code&gt; extension method encodes a string as a GUID. This method takes a string input, converts it into a hexadecimal format, and then returns a GUID based on the resulting hexadecimal string. This can be useful for scenarios like generating unique IDs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
Guid output = input.EncodeAsGuid();

// output: f2f8bf54-c72c-4db4-b35f-e21cb9cc4a4a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ConvertToHex()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ConvertToHex()&lt;/code&gt; extension method converts a string into its hexadecimal representation. Each character in the input string is converted to a two-digit hexadecimal value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
string output = input.ConvertToHex();

// output: 48656c6c6f2c20776f726c6421
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  DecodeFromHex()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string hexValue&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;DecodeFromHex()&lt;/code&gt; extension method converts a hexadecimal string into its original string representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "48656c6c6f2c20776f726c6421";
string output = input.DecodeFromHex();

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToUrlBase64()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToUrlBase64()&lt;/code&gt; extension method encodes a string as a URL-safe Base64 string. This method replaces special characters in the output string with URL-safe equivalents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
string output = input.ToUrlBase64();

// output: "SGVsbG8sIHdvcmxkIQ=="
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  FromUrlBase64()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;FromUrlBase64()&lt;/code&gt; extension method decodes a URL-safe Base64 string into its original string representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "SGVsbG8sIHdvcmxkIQ==";
string output = input.FromUrlBase64();

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantFormat()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string? format, params object?[] args&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantFormat()&lt;/code&gt; extension method formats a string with invariant culture. It is useful when formatting strings that need to be displayed across different cultures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string output = "{0} is {1} years old.".InvariantFormat("John", 30);

// output: "John is 30 years old."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToInvariantString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this int str&lt;/code&gt;, &lt;code&gt;this long str&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToInvariantString()&lt;/code&gt; extension method converts an integer or long value to its invariant string representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int input = 42;
string output = input.ToInvariantString();

// output: "42"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantEquals()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string? compare, string? compareTo&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantEquals()&lt;/code&gt; extension method compares two strings in a case-insensitive manner and with invariant culture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input1 = "Hello, world!";
string input2 = "hello, World!";
bool output = input1.InvariantEquals(input2);

// output: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantStartsWith()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string compare, string compareTo&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantStartsWith()&lt;/code&gt; extension method is used to check if a string starts with a specific substring. This method performs a case-insensitive comparison using the InvariantCultureIgnoreCase option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello World";
bool result = input.InvariantStartsWith("Hello");
// result: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantEndsWith()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string compare, string compareTo&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantEndsWith()&lt;/code&gt; extension method is used to check if a string ends with a specific substring. This method performs a case-insensitive comparison using the InvariantCultureIgnoreCase option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello World";
bool result = input.InvariantEndsWith("world");
// result: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantContains()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string compare, string compareTo&lt;/code&gt;, &lt;code&gt;this IEnumerable&amp;lt;string&amp;gt; compare, string compareTo&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantContains()&lt;/code&gt; extension methods are used to check if a string or IEnumerable of strings contains a specific substring. This method performs a case-insensitive comparison.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello World";
bool result1 = input.InvariantContains("world");
// result1: true

string[] words = { "hello", "world", "dotnet" };
bool result2 = words.InvariantContains("DoTnEt");
// result2: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantIndexOf()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string s, string value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantIndexOf()&lt;/code&gt; extension method is used to find the index of the first occurrence of a specific substring in a string. This method performs a case-insensitive comparison using the OrdinalIgnoreCase option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello World";
int index = input.InvariantIndexOf("world");
// index: 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  InvariantLastIndexOf()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string s, string value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;InvariantLastIndexOf()&lt;/code&gt; extension method is used to find the index of the last occurrence of a specific substring in a string. This method performs a case-insensitive comparison using the OrdinalIgnoreCase option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello World, hello world!";
int index = input.InvariantLastIndexOf("world");
// index: 18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ParseInto()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string val, Type type&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ParseInto()&lt;/code&gt; extension method attempts to parse a string into the supplied type by finding and using the Type's "Parse" method. It can be used to convert a string representation of a value to an instance of that value's type. There are two overloads of this method: one that returns the parsed value directly and another that returns an object that can be cast to the target type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string str = "123";
int i = (int)str.ParseInto(typeof(int));
// i: 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method also accepts a type parameter which I favour over the two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ParseInto&amp;lt;T&amp;gt;(this string val)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string str = "123";
int i = str.ParseInto&amp;lt;int&amp;gt;();
// i: 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  GenerateHash()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string str&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;GenerateHash()&lt;/code&gt; extension method is used to generate a hash of a string using a specified hash algorithm. There are two overloads of this method: one that uses the FIPS compliance setting and another that takes a generic type parameter specifying the hash algorithm to use. The default hash algorithm used by the ToSHA1 method is SHA1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string str = "Hello World!";
string md5Hash = str.GenerateHash&amp;lt;MD5&amp;gt;();
// md5Hash: "5eb63bbbe01eeed093cb22bb8f5acdc3"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToSHA1()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string stringToConvert&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToSHA1()&lt;/code&gt; extension method is a shorthand for GenerateHash("SHA1"). It is used to convert a string to its SHA1 hash value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string str = "Hello World!";
string sha1Hash = str.ToSHA1();
// sha1Hash: "0a4d55a8d778e5022fab701977c5d840bbc486d0"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  UrlTokenDecode()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;UrlTokenDecode()&lt;/code&gt; extension method decodes a string that was encoded with UrlTokenEncode. It is used to convert a string that has been encoded using the UrlTokenEncode method back to its original byte array representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string str = "SGVsbG8sIHdvcmxkIQ==";
byte[] decodedBytes = str.UrlTokenDecode(); 
// decodedBytes: [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  UrlTokenEncode()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this byte[] input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;UrlTokenEncode()&lt;/code&gt; extension method encodes a byte array for use in URLs, files, or other places where a string is required. It converts the input byte array to a Base64 string and replaces characters that could cause problems in URLs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
byte[] bytes = Encoding.UTF8.GetBytes(input);
string output = bytes.UrlTokenEncode();

// output: "SGVsbG8sIHdvcmxkIQ=="
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  NormaliseDirectoryPath()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string currentFolder&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;NormaliseDirectoryPath()&lt;/code&gt; extension method ensures that a given directory path ends with a directory separator character. It is useful when dealing with directory paths in different platforms, as Windows uses \ and Unix uses /.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = @"C:\Program Files\MyApp";
string output = input.NormaliseDirectoryPath();

// output: "C:\\Program Files\\MyApp\\"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Truncate()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, int maxLength, string suffix = "..."&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Truncate()&lt;/code&gt; extension method truncates a given string to a specified length and appends a suffix at the end of it. It is useful when displaying a long text on a user interface and we want to limit its length.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent convallis dolor vel augue imperdiet mollis.";
string output = input.Truncate(50);

// output: "Lorem ipsum dolor sit amet, consectetur adipisci..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  StripNewLines()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;StripNewLines()&lt;/code&gt; extension method removes carriage returns and line feeds from a given string. It is useful when we want to clean up a string and remove any line breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello\nWorld\r\n!";
string output = input.StripNewLines();

// output: "HelloWorld!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToSingleLine()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToSingleLine()&lt;/code&gt; extension method converts a multiline string to a single line by replacing line breaks with spaces. It is useful when we want to concatenate a multiline string into a single line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Lorem ipsum dolor sit amet,\r\nconsectetur adipiscing elit.\nSed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
string output = input.ToSingleLine();

// output: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  OrIfNullOrWhiteSpace()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input, string alternative&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;OrIfNullOrWhiteSpace()&lt;/code&gt; extension method returns the input string if it is not null or whitespace, otherwise, it returns the alternative string. It is useful when we want to provide a default value for a string if it is empty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "";
string output = input.OrIfNullOrWhiteSpace("Hello, world!");

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToFirstUpper()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;, &lt;code&gt;this string input, CultureInfo culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToFirstUpper()&lt;/code&gt; extension method converts the first character of a string to uppercase. It takes an optional CultureInfo parameter to specify the culture-specific casing rules to be used. If the input string is null or contains only whitespace, the method returns the input string without modification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "hello, world!";
string output = input.ToFirstUpper();

// output: "Hello, world!"

string input2 = "hello, world!";
string output2 = input2.ToFirstUpper(CultureInfo.GetCultureInfo("tr-TR"));

// output2: "Hello, World!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToFirstLower()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;, &lt;code&gt;this string input, CultureInfo culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToFirstLower()&lt;/code&gt; extension method converts the first character of a string to lowercase. It takes an optional CultureInfo parameter to specify the culture-specific casing rules to be used. If the input string is null or contains only whitespace, the method returns the input string without modification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "HELLO, WORLD!";
string output = input.ToFirstLower();

// output: "hELLO, WORLD!"

string input2 = "HELLO, WORLD!";
string output2 = input2.ToFirstLower(CultureInfo.GetCultureInfo("tr-TR"));

// output2: "hello, World!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToFirstUpperInvariant() / ToFirstLowerInvariant()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string input&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToFirstUpperInvariant()&lt;/code&gt; and &lt;code&gt;ToFirstLowerInvariant()&lt;/code&gt; extension methods are similar to &lt;code&gt;ToFirstUpper()&lt;/code&gt; and &lt;code&gt;ToFirstLower()&lt;/code&gt;, respectively, but they use the casing rules of the invariant culture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "hello, world!";
string output = input.ToFirstUpperInvariant();

// output: "Hello, world!"

string input2 = "HELLO, WORLD!";
string output2 = input2.ToFirstLowerInvariant();

// output2: "hELLO, WORLD!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ReplaceMany()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, IDictionary&amp;lt;string, string&amp;gt; replacements&lt;/code&gt;, &lt;code&gt;this string text, char[] chars, char replacement&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ReplaceMany()&lt;/code&gt; extension method replaces multiple occurrences of a set of characters or strings in a given string with a specified replacement character or string.&lt;/p&gt;

&lt;p&gt;The first overload of the method takes an IDictionary parameter, where each key-value pair represents the string to be replaced and the string to replace it with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "The quick brown fox jumps over the lazy dog.";
var replacements = new Dictionary&amp;lt;string, string&amp;gt; { { "quick", "slow" }, { "brown", "red" } };
string output = input.ReplaceMany(replacements);

// output: "The slow red fox jumps over the lazy dog."

string input2 = "The quick brown fox jumps over the lazy dog.";
char[] chars2 = { 'q', 'b', 'f' };
char replacement2 = '-';
string output2 = input2.ReplaceMany(chars2, replacement2);

// output2: "The ---k ---rown ox jumps over the lazy dog."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ReplaceFirst()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, string search, string replace&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ReplaceFirst()&lt;/code&gt; extension method returns a new string in which only the first occurrence of a specified string is replaced by a specified replacement string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
string output = input.ReplaceFirst("o", "0");

// output: Hell0, world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Replace()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string source, string oldString, string newString, StringComparison stringComparison&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;Replace()&lt;/code&gt; extension method returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string. StringComparison specifies the type of search to use for the specified string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "HELLO, world!";
string output = input.Replace("o", "0", StringComparison.OrdinalIgnoreCase);

// output: HELL0, w0rld!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToCSharpString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string s&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToCSharpString()&lt;/code&gt; extension method converts a literal string into a C# expression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
string output = input.ToCSharpString();

// output: "Hello, world!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EscapeRegexSpecialCharacters()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EscapeRegexSpecialCharacters()&lt;/code&gt; extension method escapes all the special characters used in a regular expression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "hello[world].";
string output = input.EscapeRegexSpecialCharacters();

// output: hello\[world\]\.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ContainsAny()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string haystack, IEnumerable&amp;lt;string&amp;gt; needles, StringComparison comparison = StringComparison.CurrentCulture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ContainsAny()&lt;/code&gt; extension method checks whether a string "haystack" contains within it any of the strings in the "needles" collection and returns true if it does or false if it doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Hello, world!";
bool output = input.ContainsAny("o", "0", "1");

// output: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CsvContains()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string csv, string value&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;CsvContains()&lt;/code&gt; extension method checks if a comma-separated string (CSV) contains a given value. It splits the input string into a list and uses the Contains() method to check if the value is in the list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string csv = "apple,banana,cherry,date,elderberry";
string value = "cherry";
bool output = csv.CsvContains(value1); 
// output: true

string value2 = "kiwi";
bool output2 = csv.CsvContains(value2); 
// output2: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToFriendlyName()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string fileName&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToFriendlyName()&lt;/code&gt; extension method can convert a file name to a user-friendly name for a content item. It performs several string manipulations to transform the file name, including stripping the file extension, replacing underscores and dashes with spaces, converting to title case, and replacing consecutive spaces with a single space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string fileName = "the_quick_brown-fox.txt";
string friendlyName = fileName.ToFriendlyName(); 
// friendlyName: "The Quick Brown Fox"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToValidXmlString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToValidXmlString()&lt;/code&gt; extension method returns a new string in which all occurrences of Unicode characters that are invalid in XML files are replaced with an empty string. It uses a regular expression to filter out control characters but allows only properly-formed surrogate sequences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "This is a \u0001 test string \uDC00 with invalid characters.";
string validXmlString = text.ToValidXmlString(); 
//validXmlString: "This is a  test string  with invalid characters."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToGuid()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToGuid()&lt;/code&gt; extension method converts a string to a GUID (Globally Unique Identifier). It creates a name-based UUID using the algorithm from RFC 4122 §4.3, which generates a deterministic GUID that is dependent on the namespace and name. Depending on the input string, the resulting GUID may not be unique.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "This is a test string";
Guid guid = text.ToGuid(); 
//guid: {B6C89F6F-DA6F-3246-9F77-2CE7C8885CF5}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  NullOrWhiteSpaceAsNull()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string? text&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;NullOrWhiteSpaceAsNull()&lt;/code&gt; extension method turns a null-or-whitespace string into a null string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "  ";
string result = text.NullOrWhiteSpaceAsNull();

// result: null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  IsFullPath()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string path&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;IsFullPath()&lt;/code&gt; extension method provides a quick way to check whether a given path is a full path including drive letter. This method takes one parameter path, which is a string value representing the path to be checked.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string path = @"C:\Program Files\Microsoft";
bool isFullPath = path.IsFullPath(); 
// isFullPath: True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we are checking whether the given path &lt;code&gt;@"C:\Program Files\Microsoft"&lt;/code&gt; is a full path including drive letter. The return value is true because the path includes a drive letter.&lt;/p&gt;




&lt;h2&gt;
  
  
  ToSafeAlias()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string alias, IShortStringHelper? shortStringHelper&lt;/code&gt;, &lt;code&gt;(this string alias, IShortStringHelper shortStringHelper, bool camel&lt;/code&gt;, &lt;code&gt;this string alias, IShortStringHelper shortStringHelper, string culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToSafeAlias()&lt;/code&gt; extension method is designed to clean a string to produce a string that can be safely used in an alias. It takes a string parameter and an object of IShortStringHelper. IShortStringHelper is an interface that specifies a few methods to clean a string and return a safe one. If you don't provide a IShortStringHelper object, you will get a NullReferenceException. For this example I am using DI to inject &lt;code&gt;Umbraco.Cms.Core.Strings.IShortStringHelper&lt;/code&gt; as the &lt;code&gt;_shortStringHelper&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string alias = "Sample alias: $@$*2-+()";
string safeAlias = alias.ToSafeAlias(_shortStringHelper);

// safeAlias: "samplealias22"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also pass a bool value for camel, which means you want the alias to be camel-cased. If camel is true, then the first character of the alias will be converted to lower case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string alias = "Sample alias: $@$*2-+()";
string safeAlias = alias.ToSafeAlias(_shortStringHelper, true);

// safeAlias: "sampleAlias22"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, you can clean a string in the context of a specified culture by passing a string value for culture. The alias will then be cleaned up to be used safely as an alias in the context of that specific culture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string alias = "Sample alias: $@$*2-+()";
string safeAlias = alias.ToSafeAlias(_shortStringHelper, "en-US");

// safeAlias: "samplealias22"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToUrlSegment()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, IShortStringHelper shortStringHelper&lt;/code&gt;, &lt;code&gt;this string text, IShortStringHelper shortStringHelper, string? culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToUrlSegment()&lt;/code&gt; extension method is designed to clean a string to produce a string that can safely be used in an URL segment. It takes a string parameter and an object of IShortStringHelper. IShortStringHelper is an interface that specifies a few methods to clean a string and return a safe one. If you don't provide a IShortStringHelper object, you will get a NullReferenceException.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "Text to clean: $@$*2-+()";
string urlSegment = text.ToUrlSegment(new DefaultShortStringHelper());

// urlSegment: "text-to-clean-22"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also clean a string, using a specified culture, to produce a string that can safely be used in an URL segment by passing a string value for culture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string text = "Text to clean: $@$*2-+()";
string urlSegment = text.ToUrlSegment(new DefaultShortStringHelper(), "en-US");

// urlSegment: "text-to-clean-22"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToCleanString()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, IShortStringHelper shortStringHelper, CleanStringType stringType&lt;/code&gt;, &lt;code&gt;this string text, IShortStringHelper shortStringHelper, CleanStringType stringType, char separator&lt;/code&gt;, &lt;code&gt;this string text, IShortStringHelper shortStringHelper, CleanStringType stringType, string culture&lt;/code&gt;, &lt;code&gt;this string text, IShortStringHelper shortStringHelper, CleanStringType stringType, char separator, string culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToCleanString()&lt;/code&gt; extension method cleans a string by removing any unwanted characters and formatting it according to the provided options. This can be useful when working with strings that need to conform to certain conventions, such as URLs or file names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "The Quick Brown Fox Jumps Over The Lazy Dog.";
string output = input.ToCleanString(new DefaultShortStringHelper(), CleanStringType.UrlFriendly);

// output: "the-quick-brown-fox-jumps-over-the-lazy-dog"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, the input string is cleaned up to be URL friendly using the default short string helper. Other options for stringType include PascalCase and CamelCase. If a separator is specified, it will be used to separate words in the output string.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ToCleanString()&lt;/code&gt; method can also take an optional culture parameter to specify a specific culture to use when cleaning the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "The Quick Brown Fox Jumps Over The Lazy Dog.";
string output = input.ToCleanString(new DefaultShortStringHelper(), CleanStringType.CamelCase, '_', "en-US");

// output: "the_Quick_Brown_Fox_Jumps_Over_The_Lazy_Dog"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the input string is cleaned up to be camelCase and the separator is set to an underscore. The culture parameter is set to "en-US".&lt;/p&gt;




&lt;h2&gt;
  
  
  SplitPascalCasing()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string phrase, IShortStringHelper shortStringHelper&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;SplitPascalCasing()&lt;/code&gt; extension method splits a Pascal-cased string into a phrase separated by spaces. It is useful for displaying text in a more readable format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "PascalCasedString";
string output = input.SplitPascalCasing(new ShortStringHelper());

// output: "Pascal Cased String"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ToSafeFileName()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string text, IShortStringHelper shortStringHelper&lt;/code&gt;, &lt;code&gt;this string text, IShortStringHelper shortStringHelper, string culture&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ToSafeFileName()&lt;/code&gt; extension method cleans a string to produce a safe filename for use internally (on disk) or externally (as a URL). It replaces characters that are not safe for filenames with safe equivalents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Some filename with spaces.txt";
string output = input.ToSafeFileName(new ShortStringHelper());

// output: "Some_filename_with_spaces.txt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ToSafeFileName() extension method also has an overload that takes a culture parameter, allowing you to specify the culture context for cleaning the string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "Some filename with spaces.txt";
string output = input.ToSafeFileName(new ShortStringHelper(), "en-US");

// output: "Some_filename_with_spaces.txt"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  EscapedSplit()
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;this string value, char splitChar, char escapeChar = DefaultEscapedStringEscapeChar&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;EscapedSplit()&lt;/code&gt; extension method splits a string with an escape character that allows for the split character to exist within the string. This is useful when dealing with strings that contain characters that are used to split the string into parts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string input = "one|two\\|three|four";
IEnumerable&amp;lt;string&amp;gt; output = input.EscapedSplit('|', '\\');

// output: ["one", "two|three", "four"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;









&lt;p&gt;Source: &lt;a href="https://github.com/umbraco/Umbraco-CMS/blob/e550a4ce3acfeffe1e7d08568df1a401a60adb11/src/Umbraco.Core/Extensions/StringExtensions.cs"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Thank You For Reading!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;What are your favourites? Let me know in the comments section below 👇&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>umbraco</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Codegarden 2022 - The Umbraco Keynote Breakdown</title>
      <dc:creator>Andy Boot</dc:creator>
      <pubDate>Sun, 30 Oct 2022 10:00:07 +0000</pubDate>
      <link>https://forem.com/andy_boot/codegarden-2022-the-umbraco-keynote-breakdown-5d9j</link>
      <guid>https://forem.com/andy_boot/codegarden-2022-the-umbraco-keynote-breakdown-5d9j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was written shortly after Umbraco Codegarden 2022 which ended on Friday, 17th June 2022. Parts of this article may have changed at the time of publication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;
The Umbraco Keynote

&lt;ul&gt;
&lt;li&gt;MVP's&lt;/li&gt;
&lt;li&gt;New vision&lt;/li&gt;
&lt;li&gt;Product Focused&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Umbraco Product Updates

&lt;ul&gt;
&lt;li&gt;Umbraco Cloud&lt;/li&gt;
&lt;li&gt;Umbraco Heartcore&lt;/li&gt;
&lt;li&gt;Umbraco Forms&lt;/li&gt;
&lt;li&gt;Umbraco CMS&lt;/li&gt;
&lt;li&gt;DXP&lt;/li&gt;
&lt;li&gt;Long-term Support (LTS) and End-of-Life (EOL)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Video Replay&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Codegarden is the biggest annual one-of-a-kind knowledge-sharing conference in the world, and I was proud to be representing Pixel Builders. The event was held between Wednesday, 15th June 2022 to Friday, 17th June 2022 in Odense, Denmark and for the first time ever it is a hybrid event which had both in-person &amp;amp; virtual attendees (pre-COVID it was traditionally in-person attendees only). I was fortunate to be attending as an unlimited access virtual attendee for a second year running (last year it was free and virtual only) and went full throttle with my listening ears with the hope to learn one or two new things. &lt;/p&gt;

&lt;h1&gt;
  
  
  The Umbraco Keynote
&lt;/h1&gt;

&lt;p&gt;With every Codegarden comes a traditional opening Keynote to kick things off. The Keynote included a look back at the past year, including several announcements and things to look forward to in the future. The speakers on stage were Kim Sneum Madsen, Filip Bech-Larsen and Emma Burstow. Umbraco welcomed a special guest on stage to kick things off with Peter Rahbæk Juel, the mayor of Odense who gave a warm welcome to all Codegarden attendees. &lt;/p&gt;

&lt;h2&gt;
  
  
  MVP’s
&lt;/h2&gt;

&lt;p&gt;The session began honouring 7 new &amp;amp; 59 renewed Umbraco MVP’s (“Most Valuable People”). Congratulations to all those people who have received this unique title. #H5YR!&lt;/p&gt;

&lt;p&gt;Notable mentions to the 7 new 2022 MVP's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/CorneHoskam"&gt;Corné Hoskam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/jasonelkin86"&gt;Jason Elkin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/JesperMayn"&gt;Jesper Mayntzhusen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/JokeVanHamme"&gt;Joke Van Hamme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/mattou07"&gt;Matthew Hart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/nurhakkaya14"&gt;Nurhak Kaya&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/Shazwazza"&gt;Shannon Deminick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More about the 2022 MVP's can be found here: &lt;a href="https://umbraco.com/blog/the-umbraco-2022-mvps/"&gt;https://umbraco.com/blog/the-umbraco-2022-mvps/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New vision
&lt;/h2&gt;

&lt;p&gt;Umbraco HQ have a positive future ahead of themselves and have set quite a few goals which they’re hoping to all accomplish by the end of 2027. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Umbraco Cloud including strong headless offering, is the preferred CMS for partners and mid-market to lower enterprise customers by continuing to be #1 in editing experience and the most loved CMS by developers&lt;/li&gt;
&lt;li&gt;That we enable customers and partners to compose their preferred tech stack by simplifying integrations – Composable DXP&lt;/li&gt;
&lt;li&gt;Continue developing and innovating Umbraco CMS together with a growing and thriving Umbraco Community ensuring true outside-in perspective. Resulting in us having more than 2 million websites running on Umbraco.&lt;/li&gt;
&lt;li&gt;Global coverage (24/7/365) with national/regional offices covering our key markets&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Which direction?
&lt;/h2&gt;

&lt;p&gt;Umbraco has been trying to map what the competitive landscape looks like and where it sees itself in the future and where it sees itself now. Currently it sees itself in the lower mid-market segment (along with Orchard, DNN, Joomal) and the vision is that they see themselves in the upper market and enterprise DXP space (along with Sitecore, Optimizely and Kentico). Heartcore also shares a similar vision within the CMS space (along with Contentful). Umbraco HQ have rest assured that they won’t leave people behind and CMS will continue to live on as it currently does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3k1s79be8486shdpxqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3k1s79be8486shdpxqe.png" alt="Umbraco's direction in the market" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Product Focused
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Commercial &amp;amp; Open Source – The great thing about having an open-source platform of which all of their commercial products are based upon is that community contributions which make their way into a final release enhance and improve the experience of products such as Umbraco Cloud and Heartcore given they inherit those same features.&lt;/li&gt;
&lt;li&gt;Open source is about transparency – Their values are about openness and being transparent about what they’re doing. One of the values is openness that speaks to the same point and want to share as much information as they can about what, why, how they do it and what the long-term plans are.&lt;/li&gt;
&lt;li&gt;Listening to feedback – Proactive in listening to feedback over the last year from developers, agencies, end-users, editor &amp;amp; partners. There is a new community team listening to feedback from the community&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Umbraco Product Updates
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Umbraco Cloud
&lt;/h2&gt;

&lt;p&gt;Umbraco Cloud is one of the available commercial offerings and is the one-stop-shop for all your Umbraco needs - the fastest, easiest, and best way to work with the most advanced open-source .NET CMS. Everything is installed, configured, and ready for development. Just click Create Project and in a few steps, Umbraco CMS is up and running.&lt;/p&gt;

&lt;p&gt;It will speed up your time-to-market, allows you to spend your time on features and helps you stay safe and up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best place to host Umbraco
&lt;/h3&gt;

&lt;p&gt;Umbraco vision is that they want it to be the best place to host Umbraco CMS want to push it to everybody as a no-brainer solution to choose Cloud for all of your products. A few key features which were highlighted were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment of culture &amp;amp; hostnames&lt;/li&gt;
&lt;li&gt;Static outgoing IP&lt;/li&gt;
&lt;li&gt;Transport security options&lt;/li&gt;
&lt;li&gt;2 Factor Authentication (2FA)&lt;/li&gt;
&lt;li&gt;Partial restore of forms&lt;/li&gt;
&lt;li&gt;Named firewall rules&lt;/li&gt;
&lt;li&gt;Content Comparison&lt;/li&gt;
&lt;li&gt;Schema comparison and configuration surfacing&lt;/li&gt;
&lt;li&gt;CDN – Now an out of the box feature running Cloudflare&lt;/li&gt;
&lt;li&gt;Backoffice User Group Selection&lt;/li&gt;
&lt;li&gt;Domain Deployment&lt;/li&gt;
&lt;li&gt;Usage metrics and top10&lt;/li&gt;
&lt;li&gt;New infrastructure on Azure&lt;/li&gt;
&lt;li&gt;Umbraco 9/10 &amp;amp; .Net 5+&lt;/li&gt;
&lt;li&gt;Deploy Dashboard&lt;/li&gt;
&lt;li&gt;Single Sign-On (SSO)&lt;/li&gt;
&lt;li&gt;Member deployment&lt;/li&gt;
&lt;li&gt;Restore options&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Updated cloud plans
&lt;/h3&gt;

&lt;p&gt;Umbraco Cloud has 3 premium plans which customers can choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starter – Restricted to 500 content nodes, 50000 page views per month, 5 GB media storage, 50GB bandwidth per month and 3 custom domains.&lt;/li&gt;
&lt;li&gt;Standard – Restricted to 2500 content nodes, 250000 page views per month, 50 GB media storage, 300GB bandwidth per month and 10 custom domains.&lt;/li&gt;
&lt;li&gt;Professional - Restricted to 7500 content nodes, 750000 page views per month, 500 GB media storage, 1000GB bandwidth per month and 50 custom domains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From now on, all the above plans can have unlimited content nodes, page views per month and many more custom domains to associate with their site. All for no extra cost when compared to before.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s next for Cloud?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;2FA for Umbraco ID&lt;/li&gt;
&lt;li&gt;Scheduled and API driven content transfers – deploy content changes at the right time.&lt;/li&gt;
&lt;li&gt;Secret management – A secure place to store API keys or any other private settings&lt;/li&gt;
&lt;li&gt;US Region with more regions to follow later&lt;/li&gt;
&lt;li&gt;Dedicated resources – 3 exclusive options to choose a dedicated option for reasonable prices for exclusivity.&lt;/li&gt;
&lt;li&gt;More to come! What out for the roadmap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about the Umbraco Cloud updates here: &lt;a href="https://umbraco.com/blog/umbraco-cloud-update-june-2022/"&gt;https://umbraco.com/blog/umbraco-cloud-update-june-2022/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Umbraco Heartcore
&lt;/h2&gt;

&lt;p&gt;Umbraco Heartcore is a headless CMS that's friendly for editors and flexible for developers. It's built on top of the open-source CMS and a collaboration with Cloudflare.&lt;/p&gt;

&lt;p&gt;A few key features from the last year:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scaled with Cloudflare&lt;/li&gt;
&lt;li&gt;Content notifications&lt;/li&gt;
&lt;li&gt;Eye dropper color picker&lt;/li&gt;
&lt;li&gt;Umbraco ID&lt;/li&gt;
&lt;li&gt;BlockList editor&lt;/li&gt;
&lt;li&gt;Improved caching&lt;/li&gt;
&lt;li&gt;Data Property Editor&lt;/li&gt;
&lt;li&gt;Content Delivery Platform&lt;/li&gt;
&lt;li&gt;New infrastructure&lt;/li&gt;
&lt;li&gt;Google Maps Property Editor&lt;/li&gt;
&lt;li&gt;Extended GraphQL support&lt;/li&gt;
&lt;li&gt;Dedicated issue-tracker&lt;/li&gt;
&lt;li&gt;Edge-side caching&lt;/li&gt;
&lt;li&gt;GraphQL Persisted queries – now available to all plans!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Roadmap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Custom Grid editors&lt;/li&gt;
&lt;li&gt;Custom Property Editors&lt;/li&gt;
&lt;li&gt;Secured Webhooks&lt;/li&gt;
&lt;li&gt;Zapier for Forms&lt;/li&gt;
&lt;li&gt;REST API v3 on OpenAPI&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Umbraco Forms
&lt;/h2&gt;

&lt;p&gt;With the latest set of releases, Umbraco Forms now makes it easy to organise thanks to its new folder structure which can individually be permissions based so you can assign the right responsibilities to specific personnel. Another great new feature is being able to localise the editing experience with your editors so they can enjoy the UI in their native language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roadmap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Improvements for Workflow &amp;amp; multi-step forms&lt;/li&gt;
&lt;li&gt;Backoffice Form previews&lt;/li&gt;
&lt;li&gt;Still 249 USD &amp;amp; Free in Cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Umbraco CMS
&lt;/h2&gt;

&lt;p&gt;Umbraco now runs .Net 5 and .Net 6. As of June 2022, Umbraco 9 has overtaken Umbraco 8 with the number of dashboard requests. Since launch, there’s been 13 releases shipped for Umbraco CMS version 9. These have included the following new features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telemetry options – A feature since Umbraco 8.1 which sends statistical data to Umbraco HQ about how Umbraco is used. This is a feature regardless of the environment, however there is the ability to opt out.&lt;/li&gt;
&lt;li&gt;Content Version Clean-up&lt;/li&gt;
&lt;li&gt;Stabilisation&lt;/li&gt;
&lt;li&gt;User &amp;amp; Member 2FA&lt;/li&gt;
&lt;li&gt;Package telemetry - Statistics show that 54.88% of packages used on sites were community created, but only 24.56% were by HQ. Most used packages being Umbraco Forms, Umbraco Deploy, Umbraco ID, uSync, Contentment, HeartCore &amp;amp; GMaps.&lt;/li&gt;
&lt;li&gt;Item tracking - Warning to prevent related content from affecting others&lt;/li&gt;
&lt;li&gt;Easy external login providers for members&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is now a release cadence of new major releases every 6 months (June &amp;amp; December) and 6 weeks for every minor version. This aims to reduce the number of changes with each upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Umbraco 10
&lt;/h3&gt;

&lt;p&gt;Out of pure coincidence, Umbraco’s next flagship version was released on day 2 of Codegarden (16/06/2022). The first all public and feature complete release candidate was released on 04/05/2022 and has had 5 release candidates available until launch.&lt;/p&gt;

&lt;p&gt;Umbraco 10 has a few major upgrades since Umbraco 9, these include the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nullable reference types – Following on from Microsoft’s own best practices, this helps a developer minimise the likelihood that code causes the runtime to throw a Null Reference Exception.&lt;/li&gt;
&lt;li&gt;SQLite – Replaces SQL CE (Compact Edition) which caused limitations with .Net 6. SQLite is cross platform, fast embedded database perfect for development and small sites.&lt;/li&gt;
&lt;li&gt;Microsoft .Net 6 – The latest long-term support (LTS) version their flagship cross platform framework. Microsoft ships with a new LTS .Net version every second year which falls in line with Umbraco LTS release schedule (see below).

&lt;ul&gt;
&lt;li&gt;3rd party packages –&lt;/li&gt;
&lt;li&gt;Imagesharp 2 – Image manipulation library now with native WebP support.&lt;/li&gt;
&lt;li&gt;Examine 3 – The search abstraction and library now build on the latest version of Lucene.Net&lt;/li&gt;
&lt;li&gt;NPoco 5 – Object-relational mapping&lt;/li&gt;
&lt;li&gt;AngularJS&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cross platform support – Starting from version 10, Umbraco is now officially supported on UNIX. With the experiences from version 9, core devs on multiple platforms, and support for a cross-platform embedded database, you can use Umbraco 10 on all UNIX platforms.&lt;/li&gt;
&lt;li&gt;Cleaner code base – More Umbraco files have been moved out of the projects file set and embedded within the Umbraco class libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about the Umbraco 10 release here: &lt;a href="https://umbraco.com/blog/umbraco-10-release/"&gt;https://umbraco.com/blog/umbraco-10-release/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Permissions for variants – Expected in Umbraco 11 (2022 Q4)&lt;/li&gt;
&lt;li&gt;Block Grid Editor – Work in progress to replaces the old Grid Editor. Block Editor Meets Grid Editor. – Expected in Umbraco 11 (2022 Q4)&lt;/li&gt;
&lt;li&gt;Entity Framework (EF) Core – Expected in Umbraco 12 (2023 Q2)&lt;/li&gt;
&lt;li&gt;Headless API – Adding headless to the core! – Expected in Umbraco 12 (2023 Q2)&lt;/li&gt;
&lt;li&gt;Block level variation – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;Content reuse – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;Enterprise focus – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;New ORM – In the future. Replacement for NPoco. – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;Lazy Loaded Content – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;Webhooks – Expected in Umbraco 13 (2023 Q4)&lt;/li&gt;
&lt;li&gt;New Backoffice – In the future. Get rid of AngularJS &amp;amp; technical debt from old framework. 3 parts:

&lt;ul&gt;
&lt;li&gt;Standalone UI library (uui.umbraco.com)&lt;/li&gt;
&lt;li&gt;Well-defined API&lt;/li&gt;
&lt;li&gt;New implementation

&lt;ul&gt;
&lt;li&gt;RFC out – RFC 0024 – Implement the New Backoffice&lt;/li&gt;
&lt;li&gt;New prototype&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Aiming for Umbraco 13 – Dec 23&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about the future of Umbraco CMS here: &lt;a href="https://umbraco.com/blog/umbraco-cms-roadmap-something-to-look-forward-to/"&gt;https://umbraco.com/blog/umbraco-cms-roadmap-something-to-look-forward-to/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DXP (Digital Experience Platform)
&lt;/h2&gt;

&lt;p&gt;Umbraco sees itself as a Composable DXP – a DXP assembled from integrating a series of externally run best-of-breed solutions that work together via APIs and leverage microservices architecture. These include (but not limited to) the following technology partners:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commercetools - &lt;a href="https://umbraco.com/blog/integrating-umbraco-cms-with-commercetools/"&gt;https://umbraco.com/blog/integrating-umbraco-cms-with-commercetools/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hubspot - &lt;a href="https://umbraco.com/blog/integrating-umbraco-forms-with-hubspot-crm/"&gt;https://umbraco.com/blog/integrating-umbraco-forms-with-hubspot-crm/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SEMrush - &lt;a href="https://umbraco.com/blog/integrating-umbraco-cms-with-semrush/"&gt;https://umbraco.com/blog/integrating-umbraco-cms-with-semrush/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Zapier - &lt;a href="https://our.umbraco.com/documentation/tutorials/Connecting-Umbraco-Forms-and-Zapier/"&gt;https://our.umbraco.com/documentation/tutorials/Connecting-Umbraco-Forms-and-Zapier/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google Search Console - &lt;a href="https://umbraco.com/blog/integrating-umbraco-cms-with-google-search-console-url-inspection-tool/"&gt;https://umbraco.com/blog/integrating-umbraco-cms-with-google-search-console-url-inspection-tool/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Shopify - &lt;a href="https://umbraco.com/blog/integrating-umbraco-cms-with-shopify/"&gt;https://umbraco.com/blog/integrating-umbraco-cms-with-shopify/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There will also be a new Umbraco Marketplace which will replace the Our Packages catalog (&lt;a href="https://our.umbraco.com/packages/"&gt;https://our.umbraco.com/packages/&lt;/a&gt;) which will be populated from NuGet with packages tagged “umbraco-marketplace”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long-term Support (LTS) and End-of-Life (EOL)
&lt;/h2&gt;

&lt;p&gt;This wasn't mentioned in the keynote, however it's still worth mentioning.&lt;/p&gt;

&lt;p&gt;So as already noted above that Umbraco CMS will release a LTS version every 2 years (or every 4th major version) to coincide with the Microsoft release schedule for each LTS version of .Net (formally .Net Core). These versions (i.e., 10, 13, 17) will have an extended support and security phase when compared with the non-LTS versions (i.e., 9, 11, 12) which will see a shorter support and security phase before eventually seeing an earlier EOL in comparison.&lt;/p&gt;

&lt;p&gt;Whilst a product version is still within a support phase, it will receive bug fixes, regressions, and security patches. These will be released as per a fixed release cadence of every 6 weeks. After the support phase we will enter the security phase which continue to receive security fixes as per the 6-week release cadence. Once the product has reached EOL it will no longer continue to see any releases. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm15gclhwpzcaek3dm668.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm15gclhwpzcaek3dm668.png" alt="Long-term Support (LTS) and End-of-Life (EOL)" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More information about this and other Umbraco products can be found on the Umbraco knowledge center: &lt;a href="https://umbraco.com/products/knowledge-center/long-term-support-and-end-of-life/"&gt;https://umbraco.com/products/knowledge-center/long-term-support-and-end-of-life/&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Another interesting article I found by Eric Seng, which consolidates all the information regarding LTD &amp;amp; EOL for the .NET family can be read here: &lt;a href="https://blog.inedo.com/dotnet/3-dotnet-lts-charts"&gt;https://blog.inedo.com/dotnet/3-dotnet-lts-charts&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Video Replay
&lt;/h1&gt;

&lt;p&gt;If you'd like to watch the Keynote for yourself, then Umbraco have now uploaded this to YouTube:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7HDiqhIPgSA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also access all the other talks made over the 3 day period:&lt;br&gt;
&lt;a href="https://www.youtube.com/playlist?list=PLG_nqaT-rbpx7QcHtQE4Efr83U6Lqf4Fp"&gt;https://www.youtube.com/playlist?list=PLG_nqaT-rbpx7QcHtQE4Efr83U6Lqf4Fp&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Thank you for taking the time to read this article. I'm hoping you managed to take away some useful insights and gave you a clearer vision of Umbraco's future.&lt;/p&gt;

&lt;p&gt;If this article has helped you in any way, or would like to provide any constructive feedback please drop me a comment below.&lt;/p&gt;

</description>
      <category>umbraco</category>
      <category>codegarden</category>
    </item>
    <item>
      <title>Umbraco Forms - Add additional attributes to existing field types</title>
      <dc:creator>Andy Boot</dc:creator>
      <pubDate>Tue, 25 Oct 2022 15:43:01 +0000</pubDate>
      <link>https://forem.com/andy_boot/umbraco-forms-add-additional-attributes-to-existing-field-types-4abg</link>
      <guid>https://forem.com/andy_boot/umbraco-forms-add-additional-attributes-to-existing-field-types-4abg</guid>
      <description>&lt;p&gt;We've all been there; the website designers introduce additional elements or layout which the off the shelf tools simply cannot cater for.&lt;/p&gt;

&lt;p&gt;Recently I encountered this issue for building what I originally thought was a simple contact form with a relatively straightforward layout. Here's a similar mock-up of the design I was provided:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmycfs0ijnyozekdgimdh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmycfs0ijnyozekdgimdh.jpg" alt="Mock-up"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main contact form on the right looks somewhat straightforward enough which Umbraco Forms can easily accommodate for, right?&lt;/p&gt;

&lt;p&gt;Let's get started with a first draft of the form configuration:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxga574qxzj1cxgzxcuv1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxga574qxzj1cxgzxcuv1.png" alt="Umbraco Forms First Draft Form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, I've managed to create the 2 groups for the 'Your details' and 'Enquiry type' areas. Each area appears to be set within a 2-column grid layout, so I've configured it like so. So far so good, but here's my problem... how on Earth do I allow fields such as 'Company Name' to span across both grid columns?&lt;/p&gt;

&lt;p&gt;Well, as far as I can initially tell there's no clear-cut way of doing this, given you can only define the column layout on the group and not on a per row basis. Each column is just a container where each field stacks upon one another. &lt;em&gt;Perhaps in future versions we'll see an expansion of this so groups are able to create rows, and each row creates the columns.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, plan B. Scrap two columns in our group containers at HTML level, but instead add each field on a single column basis and use CSS to structure the layout (1 or 2 columns). However, we also need a mechanism to tell each field how many columns it should span.&lt;/p&gt;

&lt;p&gt;The Umbraco Forms API allows us to extend the original implementation of field types to perform additional duties such as custom field validation, alternative views or more importantly adding our own attributes!&lt;/p&gt;

&lt;p&gt;As our 'Company Name' field is basic textbox (AKA 'Short Answer'), we'll focus our efforts on adapting this, and if it works apply it to other related field types afterwards.&lt;/p&gt;

&lt;p&gt;First we'll create a new C# class, inherit from &lt;code&gt;Umbraco.Forms.Core.Providers.FieldTypes.Textfield&lt;/code&gt;, add a new checkbox attribute named 'Span all columns?' and leave as is. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyProject.UmbracoForms.CustomFieldTypes&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Textfield&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Umbraco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Textfield&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Umbraco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Span all columns?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allows the field to span across both columns in the layout."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;View&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Checkbox"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;SpanAllColumns&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Textfield&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We also need a composer to register this inherited class to tell Umbraco Forms to use our custom field type instead of the default one:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyProject.UmbracoForms.Composers&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UmbracoFormsCustomProvidersComposer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IComposer&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Compose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUmbracoBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FormsFields&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Textfield&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If we build our project and refresh the browser, we can now see our freshly added checkbox toggle against each of our 'Short Answer' fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7q71520y3rzb5u8ftsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7q71520y3rzb5u8ftsd.png" alt="Newly added attribute"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, with our new attribute in place we can now instruct the HTML output to add a CSS class to one of the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements which wraps our field type.&lt;/p&gt;

&lt;p&gt;Using the 'default' Umbraco Forms theme as an example, I've modified the &lt;code&gt;Form.cshtml&lt;/code&gt; file with the following changes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="nf"&gt;@foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FieldViewModel&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;hidden&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasCondition&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConditionActionType&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;FieldConditionActionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// REFERENCE 1&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;spanAllColumns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AdditionalSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SpanAllColumns"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AdditionalSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"SpanAllColumns"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"True"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fieldTypeCols&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spanAllColumns&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// REFERENCE 2&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="nc"&gt;col&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;@fieldTypeCols&lt;/span&gt; &lt;span class="n"&gt;@Html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetFormFieldWrapperClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FieldTypeName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;@f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CssClass&lt;/span&gt;&lt;span class="s"&gt;" @{ if (hidden) { &amp;lt;text&amp;gt; style="&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="s"&gt;" &amp;lt;/text&amp;gt;  } }&amp;gt;
&lt;/span&gt;
        &lt;span class="nf"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HideLabel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@f.Id"&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="nc"&gt;umbraco&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="s"&gt;"&amp;gt;
&lt;/span&gt;                &lt;span class="n"&gt;@f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Caption&lt;/span&gt; &lt;span class="nf"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShowIndicator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="nc"&gt;umbraco&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt;&lt;span class="s"&gt;"&amp;gt;@Model.Indicator&amp;lt;/span&amp;gt;
&lt;/span&gt;                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToolTip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="nc"&gt;umbraco&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tooltip&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="s"&gt;"&amp;gt;@f.ToolTip&amp;lt;/span&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;&lt;span class="nc"&gt;umbraco&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;wrapper&lt;/span&gt;&lt;span class="s"&gt;"&amp;gt;
&lt;/span&gt;
            &lt;span class="n"&gt;@await&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PartialAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FormThemeResolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetFieldView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nf"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShowFieldValidaton&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;@Html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ValidationMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Please locate &lt;code&gt;REFERENCE 1&lt;/code&gt; and &lt;code&gt;REFERENCE 2&lt;/code&gt; in the code above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REFERENCE 1 - Added a boolean variable named &lt;code&gt;spanAllColumns&lt;/code&gt; to retrieve our new field type value (if exists). Also added an integer variable named &lt;code&gt;fieldTypeCols&lt;/code&gt; to set the number of columns to either 6 or 12 based on our preference.&lt;/li&gt;
&lt;li&gt;REFERENCE 2 - Added &lt;code&gt;col-md-@fieldTypeCols&lt;/code&gt; to the class property of the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intended output after all this is something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmv9gpnygyf3c5upcwsi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmv9gpnygyf3c5upcwsi.png" alt="Rendered page with intended layout"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The 'Company Name' field now spans both columns thanks to it using all 12 Bootstrap 3 grid columns instead of the default 6. Now all that's left to do is to replicate our changes for the Textarea field type exactly the same as we did for the Textfield and the core basics are done.&lt;/p&gt;




&lt;p&gt;Thank you for taking the time to read this article. Hopefully this helps somebody in their quest to perform the same task, or something similar.&lt;/p&gt;

&lt;p&gt;If this article has helped you in any way, or would like to provide any constructive feedback please drop me a comment below.&lt;/p&gt;

</description>
      <category>umbraco</category>
      <category>umbracoforms</category>
      <category>dotnet</category>
      <category>hacktoberfest</category>
    </item>
  </channel>
</rss>
