<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://vandsh.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vandsh.github.io/" rel="alternate" type="text/html" /><updated>2026-01-08T23:07:41+00:00</updated><id>https://vandsh.github.io/feed.xml</id><title type="html">vandsh - breaker of things</title><subtitle>Steve Vandenbush - Jack of all trades, master of none? Love all things code. Software Engineer at Heartland Business Systems. These are just some of my ramblings.</subtitle><entry><title type="html">Entra External ID: Custom Claims and the Portal of Lies</title><link href="https://vandsh.github.io/azure/2026/01/08/entra-external-id-custom-attributes.html" rel="alternate" type="text/html" title="Entra External ID: Custom Claims and the Portal of Lies" /><published>2026-01-08T00:00:00+00:00</published><updated>2026-01-08T00:00:00+00:00</updated><id>https://vandsh.github.io/azure/2026/01/08/entra-external-id-custom-attributes</id><content type="html" xml:base="https://vandsh.github.io/azure/2026/01/08/entra-external-id-custom-attributes.html"><![CDATA[<p>So, Microsoft is slowly sunsetting Azure AD B2C (thank god, no more XML policies, right?). The replacement is <strong>Entra External ID</strong> (or CIAM). The pitch is great: “It’s just standard Entra ID under the hood!”</p>

<p>That sounds fantastic until you try to do the one thing everyone actually uses these platforms for: <strong>collecting a custom field during sign-up and shoving it into the token.</strong></p>

<p>I recently spent way too long trying to get a simple custom attribute (<code class="language-plaintext highlighter-rouge">MemberId</code>) to show up in a JWT. Here is the breakdown of how to do it, and more importantly, how to actually get the data out without losing your mind.</p>

<h2 id="the-new-world-briefly">The New World (Briefly)</h2>

<p>If you are coming from B2C, forget the <code class="language-plaintext highlighter-rouge">Identity Experience Framework</code>. CIAM uses <strong>User Flows</strong> (the easy GUI ones) for almost everything.</p>

<p>If you need custom logic (like validating a Member ID or generating one), you don’t call a REST API from an XML policy anymore. You use <strong>Custom Authentication Extensions</strong>. These trigger Azure Functions at specific events, like <code class="language-plaintext highlighter-rouge">OnAttributeCollectionSubmit</code>.</p>

<p>It’s cleaner, honestly. I wired up a Function to validate my <code class="language-plaintext highlighter-rouge">MemberId</code> and it worked immediately. The data was saved to the user profile.</p>

<h2 id="the-problem-the-case-of-the-missing-claim">The Problem: The Case of the Missing Claim</h2>

<p>I had the <code class="language-plaintext highlighter-rouge">MemberId</code> in the directory. I verified it via Graph Explorer. It was there, staring me in the face with its ugly extension name:</p>

<p>But when I logged in? My ID Token looked like this:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"aud"</span><span class="p">:</span><span class="w"> </span><span class="s2">"efe03d75..."</span><span class="p">,</span><span class="w">
  </span><span class="nl">"iss"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://..."</span><span class="p">,</span><span class="w">
  </span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"steve@example.com"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Steve"</span><span class="w">
</span><span class="p">}</span><span class="w">

</span></code></pre></div></div>

<p>No Member ID. Nothing. Just standard claims.</p>

<h2 id="trap-1-the-null-value">Trap #1: The Null Value</h2>

<p>First technical “gotcha” of CIAM: <strong>If a custom attribute is null, it is dropped.</strong></p>

<p>It doesn’t send a <code class="language-plaintext highlighter-rouge">null</code> value. It doesn’t send an empty string. The claim just ceases to exist. So if your Azure Function fails to write the data, or you mess up the casing on the attribute name (it’s case-sensitive, by the way), you will be debugging a phantom.</p>

<p>Always check Graph Explorer first. If the data isn’t on the user object, stop debugging the token. Fix the save.</p>

<h2 id="trap-2-the-red-herring-app-registration">Trap #2: The Red Herring (App Registration)</h2>

<p>If you Google this, you will find documentation telling you to manually edit the <code class="language-plaintext highlighter-rouge">optionalClaims</code> in the App Registration Manifest. <strong>Don’t.</strong> That is a rabbit hole of case-sensitivity issues and <code class="language-plaintext highlighter-rouge">source: null</code> errors.</p>

<p>You only need to do two things in your <strong>App Registration</strong>:</p>

<ol>
  <li><strong>Permissions:</strong> Ensure your app has <code class="language-plaintext highlighter-rouge">User.Read</code> permission on Microsoft Graph and—crucially—<strong>Grant Admin Consent</strong>.</li>
  <li><strong>Manifest:</strong> Toggle one specific flag to allow the token issuer to accept custom maps.</li>
</ol>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"acceptMappedClaims"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">

</span></code></pre></div></div>

<p>That’s it. Close the App Registration. You are done there.</p>

<h2 id="the-real-fix-enterprise-applications">The Real Fix: Enterprise Applications</h2>

<p>The actual working UI for mapping and renaming claims in CIAM is hidden in the <strong>Enterprise Application</strong> blade (the service principal instance), not the App Registration definition.</p>

<p>Go to <strong>Enterprise Applications</strong> -&gt; Find your app.</p>

<p>Click <strong>Single sign-on</strong> (even if you are using OIDC/OAuth, this is where the UI lives).</p>

<p><img src="/assets/easso1.webp" alt="Enterprise Application, Single sign-on" /></p>

<p>Click <strong>Edit</strong> on the <strong>Attributes &amp; Claims</strong> box.</p>

<p><img src="/assets/easso2.webp" alt="Enterprise Application, Attributes &amp; Claims" /></p>

<p>This is the only place that actually lets you see the hidden <code class="language-plaintext highlighter-rouge">b2c-extensions-app</code> schema without using PowerShell.</p>

<p><img src="/assets/easso3.webp" alt="Enterprise Application, Attributes &amp; Claims, Select" /></p>

<p>When you add a new claim, change the <strong>Source</strong> to <strong>Directory schema extension</strong>. You will be able to select the backend extension app that holds your custom data.</p>

<p>Select your attribute from the list.</p>

<p><img src="/assets/easso4.webp" alt="Enterprise Application, Attributes &amp; Claims, Select" /></p>

<p>Finally, give it the clean name you actually want in your code (e.g., <code class="language-plaintext highlighter-rouge">memberId</code> instead of <code class="language-plaintext highlighter-rouge">extension_&lt;your-app-guid-here&gt;_MemberId</code>).</p>

<h2 id="the-result">The Result</h2>

<p>Once I saved that mapping in the Enterprise App, the token finally respected the data.</p>

<p><img src="/assets/easso5.webp" alt="Custom attribute in JWT Token" /></p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"steve@example.com"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"memberId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ASD123"</span><span class="w">
</span><span class="p">}</span><span class="w">

</span></code></pre></div></div>

<p>It works, but man, they really make you dig for it.</p>]]></content><author><name></name></author><category term="azure" /><category term="azure" /><category term="entra" /><category term="ciam" /><category term="identity" /><summary type="html"><![CDATA[So, Microsoft is slowly sunsetting Azure AD B2C (thank god, no more XML policies, right?). The replacement is Entra External ID (or CIAM). The pitch is great: “It’s just standard Entra ID under the hood!”]]></summary></entry><entry><title type="html">AppService to AzureSql using Managed Identity</title><link href="https://vandsh.github.io/dotnet/2022/02/02/azure-sql-managed-identity.html" rel="alternate" type="text/html" title="AppService to AzureSql using Managed Identity" /><published>2022-02-02T00:00:00+00:00</published><updated>2022-02-02T00:00:00+00:00</updated><id>https://vandsh.github.io/dotnet/2022/02/02/azure-sql-managed-identity</id><content type="html" xml:base="https://vandsh.github.io/dotnet/2022/02/02/azure-sql-managed-identity.html"><![CDATA[<p>I am guessing most of you, like me, have traditionally spun up an Azure Sql database, enabled Sql Authentication, stuffed that username and password into a connection string either in in Azure KeyVault or the <code class="language-plaintext highlighter-rouge">appsettings.config/web.config</code>.</p>

<p>I also assume if you have gotten to this post, you are either looking to change that approach on your own, have been told by your “security team” to do better or maybe some of both.</p>

<p>A lot of what I am going to detail below is lifted from <a href="https://docs.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cefcore%2Cdotnet#4-use-managed-identity-connectivity">here</a> but with a UI and some screenshots to help.</p>

<p>To preface some of what I will show here, the example project is using the following:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">dotnet 5</code></li>
  <li><code class="language-plaintext highlighter-rouge">EFCore</code></li>
  <li><code class="language-plaintext highlighter-rouge">Windows App Service</code></li>
  <li><code class="language-plaintext highlighter-rouge">Azure Sql Serverless</code></li>
</ul>

<p>I won’t be going into detail on how to setup EFCore using SqlServer as there are <a href="https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-6.0#register-the-schoolcontext">plenty of other examples</a>, but I do want to focus on how to get your App Service talking to your Azure Sql Database using a managed identity.</p>

<h3 id="azure-sql-authentication-method">Azure Sql Authentication Method</h3>

<p>If you are <em>just</em> creating your Azure Sql Server now, make sure you select <code class="language-plaintext highlighter-rouge">Use Azure Active Directory (Azure AD) authentication</code>:</p>

<p><img src="/assets/aadauth1.jpg" alt="Azure AD Auth on New setup" /></p>

<p>If you already have an Azure Sql Server and Database, go to your server and click on <code class="language-plaintext highlighter-rouge">Settings -&gt; Azure Active Directory</code>:</p>

<p><img src="/assets/aadauth2.jpg" alt="Azure AD Auth on Existing setup" /></p>

<p>By selecting this option (for either) you are effectively disabling the Sql Authentication for the server. You will also have to assign an <code class="language-plaintext highlighter-rouge">AD Admin</code> for the server, make sure to assign an admin account you have access to as you will need it shortly…</p>

<h3 id="enabling-managed-identity">Enabling Managed Identity</h3>

<p>This should be pretty straightforward, go to your App Service, find <code class="language-plaintext highlighter-rouge">Settings -&gt; Identity</code> and click <code class="language-plaintext highlighter-rouge">Status -&gt; On</code>:</p>

<p><img src="/assets/managedidentity.jpg" alt="Enabling Managed Identity" /></p>

<p>Your app service now has a proper identity.</p>

<h3 id="creating-the-contained-user">Creating the Contained User</h3>

<p>For this next step, you will need to make sure you have the server Firewall opened up enough for you to access the database and run some Sql, but you might as well grant access for the Azure Services too:</p>

<p><img src="/assets/sqlfirewall.jpg" alt="Opening Sql Firewall" /></p>

<p>Now that you have line of sight to the server, open the database and you can either open up the <code class="language-plaintext highlighter-rouge">Query Editor</code>:</p>

<p><img src="/assets/queryeditor.jpg" alt="In Browser Query Editor" /></p>

<p>Or if you rather <code class="language-plaintext highlighter-rouge">Sql Server Management Studio</code>:</p>

<p><img src="/assets/ssmsadlogin.jpg" alt="SSMS" /></p>

<p>Regardless, you need to execute the following Sql:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- WITH OBJECT_ID only needed if you have names not unique between app services and app registrations.</span>
<span class="k">CREATE</span> <span class="k">USER</span> <span class="p">[</span><span class="n">your</span><span class="o">-</span><span class="n">app</span><span class="o">-</span><span class="n">service</span><span class="p">]</span> <span class="k">FROM</span> <span class="k">EXTERNAL</span> <span class="n">PROVIDER</span> <span class="k">WITH</span> <span class="n">OBJECT_ID</span> <span class="o">=</span> <span class="s1">'a290ccc0-6142-4ff6-9620-7ea2393e6ed2'</span><span class="p">;</span>

<span class="k">ALTER</span> <span class="k">ROLE</span> <span class="n">db_datareader</span> <span class="k">ADD</span> <span class="n">MEMBER</span> <span class="p">[</span><span class="n">your</span><span class="o">-</span><span class="n">app</span><span class="o">-</span><span class="n">service</span><span class="p">];</span>
<span class="k">ALTER</span> <span class="k">ROLE</span> <span class="n">db_datawriter</span> <span class="k">ADD</span> <span class="n">MEMBER</span> <span class="p">[</span><span class="n">your</span><span class="o">-</span><span class="n">app</span><span class="o">-</span><span class="n">service</span><span class="p">];</span>
<span class="k">ALTER</span> <span class="k">ROLE</span> <span class="n">db_ddladmin</span> <span class="k">ADD</span> <span class="n">MEMBER</span> <span class="p">[</span><span class="n">your</span><span class="o">-</span><span class="n">app</span><span class="o">-</span><span class="n">service</span><span class="p">];</span>

</code></pre></div></div>

<p>Where <code class="language-plaintext highlighter-rouge">your-app-service</code> is the actual name of your App Service in Azure (please make sure this is unique, both within <code class="language-plaintext highlighter-rouge">App Services</code> but also within <code class="language-plaintext highlighter-rouge">Active Directory -&gt; App Registrations</code>). 
You will get an error upon creation if it can not find the actual resource by name, so you won’t have to worry about botching it up yet… Also make sure to use applicable roles for your App Service.</p>

<p>Alright so we have Active Directory Authentication enabled for the Sql Server, a Managed Identity for our App Service, an actual user in the database for that Identity with roles, we have the database server Firewall accepting traffic from Azure resources, all we need now is a proper connection string:</p>

<h3 id="connectionstring">ConnectionString</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Server=tcp:yourDbServer.database.windows.net;Authentication=Active Directory Default; Database=YourDatabase;
</code></pre></div></div>

<p>And realistically, at this point, you should be done!</p>

<p><em>Additional note, I ran into some odd errors about <code class="language-plaintext highlighter-rouge">authentication is 'unknown_type'</code> specifically for the ConnectionString. It had seemed to be an issue with the <code class="language-plaintext highlighter-rouge">Microsoft.Data.SqlClient</code> that is included in the EFCore SqlServer package. 
Simply by adding the <code class="language-plaintext highlighter-rouge">Microsoft.Data.SqlClient</code> package to the solution/project, to its latest version resolved this error. You may or may need to follow suit.</em></p>

<p>Happy Breaking.</p>]]></content><author><name></name></author><category term="dotnet" /><category term="dotnet" /><category term="EF" /><category term="Azure" /><category term="Sql" /><summary type="html"><![CDATA[I am guessing most of you, like me, have traditionally spun up an Azure Sql database, enabled Sql Authentication, stuffed that username and password into a connection string either in in Azure KeyVault or the appsettings.config/web.config.]]></summary></entry><entry><title type="html">SecureClientSecret one time use</title><link href="https://vandsh.github.io/dotnet/2021/03/05/secureclientsecret-single-use.html" rel="alternate" type="text/html" title="SecureClientSecret one time use" /><published>2021-03-05T00:00:00+00:00</published><updated>2021-03-05T00:00:00+00:00</updated><id>https://vandsh.github.io/dotnet/2021/03/05/secureclientsecret-single-use</id><content type="html" xml:base="https://vandsh.github.io/dotnet/2021/03/05/secureclientsecret-single-use.html"><![CDATA[<p>Hooking up <code class="language-plaintext highlighter-rouge">Graph</code> for a recent project where I wanted to obtain a little more information from <code class="language-plaintext highlighter-rouge">Azure Active Directory</code> from the user immediately after login, I started running into a few snags.</p>

<p>First, the <a href="https://github.com/microsoft/Partner-Center-Storefront/blob/35abe9e988ab2fd6f612146c74c71db8d3f0b57e/src/Storefront/App_Start/Startup.Auth.cs#L77">code I was using as a guide</a> was using the <code class="language-plaintext highlighter-rouge">authorizationCode</code> form the original sign in to obtain an access token for graph. 
That is just fine and acceptable, until you need to make another call. 
Simply put, sometime in Sept of 2018, <a href="https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/whats-new-archive#change-notice-authorization-codes-will-no-longer-be-available-for-reuse">AAD stopped letting Auth codes be reused</a>.</p>

<p>Frustrated but not defeated, I found a <a href="https://www.linkedin.com/pulse/handling-error-aadsts54005-nicholas-mccollum/">super helpful post</a> on working thru this change.</p>

<h3 id="startupauthcs">Startup.Auth.cs</h3>
<p><em>Close but not quite…</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Within OpenIdConnectAuthenticationNotifications()</span>
<span class="n">AuthorizationCodeReceived</span> <span class="p">=</span> <span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="c1">// Get these for later</span>
    <span class="kt">var</span> <span class="n">redirectUri</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">HttpContext</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">Url</span><span class="p">.</span><span class="nf">GetLeftPart</span><span class="p">(</span><span class="n">UriPartial</span><span class="p">.</span><span class="n">Path</span><span class="p">));</span>
    <span class="kt">string</span> <span class="n">signedInUserObjectId</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">AuthenticationTicket</span><span class="p">.</span><span class="n">Identity</span><span class="p">.</span><span class="nf">FindFirst</span><span class="p">(</span><span class="s">"http://schemas.microsoft.com/identity/claims/objectidentifier"</span><span class="p">).</span><span class="n">Value</span><span class="p">;</span>
    <span class="kt">string</span> <span class="n">userTenantId</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">AuthenticationTicket</span><span class="p">.</span><span class="n">Identity</span><span class="p">.</span><span class="nf">FindFirst</span><span class="p">(</span><span class="s">"http://schemas.microsoft.com/identity/claims/tenantid"</span><span class="p">).</span><span class="n">Value</span><span class="p">;</span>

    <span class="c1">// Like a good kid, we are going to store our secrets in Azure KeyVault</span>
    <span class="kt">var</span> <span class="n">redirectUri</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">HttpContext</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">Url</span><span class="p">.</span><span class="nf">GetLeftPart</span><span class="p">(</span><span class="n">UriPartial</span><span class="p">.</span><span class="n">Path</span><span class="p">));</span>
    <span class="n">KeyVaultService</span> <span class="n">keyVaultService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">KeyVaultService</span><span class="p">();</span>
    <span class="kt">var</span> <span class="n">secureString</span> <span class="p">=</span> <span class="k">await</span> <span class="n">keyVaultService</span><span class="p">.</span><span class="nf">GetAsync</span><span class="p">(</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryPortalKey</span><span class="p">);</span>
    <span class="n">SecureClientSecret</span> <span class="n">clientSecret</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">SecureClientSecret</span><span class="p">(</span><span class="n">secureString</span><span class="p">);</span>

    <span class="c1">// Obtain an access token for the current application using the authorization code (modified from that Linkedin Post)</span>
    <span class="n">ClientCredential</span> <span class="n">credential</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ClientCredential</span><span class="p">(</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryClientID</span><span class="p">,</span> <span class="n">clientSecret</span><span class="p">);</span>
    <span class="n">AuthenticationContext</span> <span class="n">authContext</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">AuthenticationContext</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryEndPoint</span><span class="p">}{</span><span class="n">userTenantId</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
    <span class="n">AuthenticationResult</span> <span class="n">result</span> <span class="p">=</span> <span class="n">authContext</span><span class="p">.</span><span class="nf">AcquireTokenByAuthorizationCodeAsync</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">ProtocolMessage</span><span class="p">.</span><span class="n">Code</span><span class="p">,</span> <span class="n">redirectUri</span><span class="p">,</span> <span class="n">credential</span><span class="p">,</span> <span class="n">context</span><span class="p">.</span><span class="n">Options</span><span class="p">.</span><span class="n">ClientId</span><span class="p">).</span><span class="n">Result</span><span class="p">;</span>

    <span class="c1">// Obtain and cache access tokens for additional resources using the access token</span>
    <span class="c1">// from the application as an assertion (modified from Linkedin Post)</span>
    <span class="n">UserAssertion</span> <span class="n">userAssertion</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">UserAssertion</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
    <span class="n">AuthenticationResult</span> <span class="n">graphResult</span> <span class="p">=</span> <span class="n">authContext</span><span class="p">.</span><span class="nf">AcquireTokenAsync</span><span class="p">(</span><span class="s">"https://graph.microsoft.com"</span><span class="p">,</span> <span class="n">credential</span><span class="p">,</span> <span class="n">userAssertion</span><span class="p">).</span><span class="n">Result</span><span class="p">;</span>
    
    <span class="c1">// Actual calls to Graph, blows up before even getting here...</span>
    <span class="n">IGraphClient</span> <span class="n">graphClient</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GraphClient</span><span class="p">(</span><span class="n">userTenantId</span><span class="p">,</span> <span class="n">graphResult</span><span class="p">);</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">RoleModel</span><span class="p">&gt;</span> <span class="n">roles</span> <span class="p">=</span> <span class="k">await</span> <span class="n">graphClient</span><span class="p">.</span><span class="nf">GetDirectoryRolesAsync</span><span class="p">(</span><span class="n">signedInUserObjectId</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="k">false</span><span class="p">);</span>
<span class="p">...</span>
</code></pre></div></div>

<p>It got me about 90% of the way there, but as we all know, it is that last 10% that is the hardest. 
The part that was failing hard was the <code class="language-plaintext highlighter-rouge">graphResult = authContext.AquireTokenAsync</code> call. 
I kept getting a terribly vague <code class="language-plaintext highlighter-rouge">Object reference not set to an instance of an object.</code> error from a proper MS class, which only added to the frustration.
Finally after hours of debugging, searching and all those things devs do when they can’t figure something out, I found a trail leading <code class="language-plaintext highlighter-rouge">SecureClientSecret</code> being one time use…</p>

<h3 id="startupauthcs-1">Startup.Auth.cs</h3>
<p><em>Much betta!</em></p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">AuthorizationCodeReceived</span> <span class="p">=</span> <span class="k">async</span> <span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="c1">// Same as above</span>
    <span class="kt">var</span> <span class="n">redirectUri</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="n">HttpContext</span><span class="p">.</span><span class="n">Current</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">Url</span><span class="p">.</span><span class="nf">GetLeftPart</span><span class="p">(</span><span class="n">UriPartial</span><span class="p">.</span><span class="n">Path</span><span class="p">));</span>
    <span class="kt">string</span> <span class="n">signedInUserObjectId</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">AuthenticationTicket</span><span class="p">.</span><span class="n">Identity</span><span class="p">.</span><span class="nf">FindFirst</span><span class="p">(</span><span class="s">"http://schemas.microsoft.com/identity/claims/objectidentifier"</span><span class="p">).</span><span class="n">Value</span><span class="p">;</span>
    <span class="kt">string</span> <span class="n">userTenantId</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">AuthenticationTicket</span><span class="p">.</span><span class="n">Identity</span><span class="p">.</span><span class="nf">FindFirst</span><span class="p">(</span><span class="s">"http://schemas.microsoft.com/identity/claims/tenantid"</span><span class="p">).</span><span class="n">Value</span><span class="p">;</span>

    <span class="c1">// Same as above</span>
    <span class="n">KeyVaultService</span> <span class="n">keyVaultService</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">KeyVaultService</span><span class="p">();</span>
    <span class="kt">var</span> <span class="n">secureString</span> <span class="p">=</span> <span class="k">await</span> <span class="n">keyVaultService</span><span class="p">.</span><span class="nf">GetAsync</span><span class="p">(</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryPortalKey</span><span class="p">);</span>
    <span class="n">SecureClientSecret</span> <span class="n">clientSecret</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">SecureClientSecret</span><span class="p">(</span><span class="n">secureString</span><span class="p">);</span>

    <span class="c1">// Same as above</span>
    <span class="n">ClientCredential</span> <span class="n">credential</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ClientCredential</span><span class="p">(</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryClientID</span><span class="p">,</span> <span class="n">clientSecret</span><span class="p">);</span>
    <span class="n">AuthenticationContext</span> <span class="n">authContext</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">AuthenticationContext</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryEndPoint</span><span class="p">}{</span><span class="n">userTenantId</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
    <span class="n">AuthenticationResult</span> <span class="n">result</span> <span class="p">=</span> <span class="n">authContext</span><span class="p">.</span><span class="nf">AcquireTokenByAuthorizationCodeAsync</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">ProtocolMessage</span><span class="p">.</span><span class="n">Code</span><span class="p">,</span> <span class="n">redirectUri</span><span class="p">,</span> <span class="n">credential</span><span class="p">,</span> <span class="n">context</span><span class="p">.</span><span class="n">Options</span><span class="p">.</span><span class="n">ClientId</span><span class="p">).</span><span class="n">Result</span><span class="p">;</span>

    <span class="c1">// Create a SECOND SecureClientSecret, just for the Graph calls...</span>
    <span class="n">SecureClientSecret</span> <span class="n">graphClientSecret</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">SecureClientSecret</span><span class="p">(</span><span class="n">secureString</span><span class="p">);</span>
    <span class="n">ClientCredential</span> <span class="n">graphClientCredential</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ClientCredential</span><span class="p">(</span><span class="n">ApplicationConfig</span><span class="p">.</span><span class="n">ActiveDirectoryClientID</span><span class="p">,</span> <span class="n">graphClientSecret</span><span class="p">);</span>
    <span class="n">UserAssertion</span> <span class="n">userAssertion</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">UserAssertion</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">AccessToken</span><span class="p">);</span>
    <span class="n">AuthenticationResult</span> <span class="n">graphResult</span> <span class="p">=</span> <span class="k">await</span> <span class="n">authContext</span><span class="p">.</span><span class="nf">AcquireTokenAsync</span><span class="p">(</span><span class="s">"https://graph.microsoft.com"</span><span class="p">,</span> <span class="n">graphClientCredential</span><span class="p">,</span> <span class="n">userAssertion</span><span class="p">);</span>
    
    <span class="c1">// No explosions, works as expected...</span>
    <span class="n">IGraphClient</span> <span class="n">graphClient</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">GraphClient</span><span class="p">(</span><span class="n">userTenantId</span><span class="p">,</span> <span class="n">graphResult</span><span class="p">);</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">RoleModel</span><span class="p">&gt;</span> <span class="n">roles</span> <span class="p">=</span> <span class="k">await</span> <span class="n">graphClient</span><span class="p">.</span><span class="nf">GetDirectoryRolesAsync</span><span class="p">(</span><span class="n">signedInUserObjectId</span><span class="p">).</span><span class="nf">ConfigureAwait</span><span class="p">(</span><span class="k">false</span><span class="p">);</span>
<span class="p">...</span>
</code></pre></div></div>

<p>Not going to lie, I feel a bit miffed at all of this. 
There is some weak documentation supporting this was done “intentionally” for security purposes. 
Having it documented in the class metadata itself or make it disposable if you are <em>that</em> concerned, anything along those lines would have saved me several hours of hair pulling.</p>

<p>Don’t worry MS, I won’t send you the bill.</p>]]></content><author><name></name></author><category term="dotnet" /><category term="dotnet" /><category term="Graph" /><category term="AD" /><summary type="html"><![CDATA[Hooking up Graph for a recent project where I wanted to obtain a little more information from Azure Active Directory from the user immediately after login, I started running into a few snags.]]></summary></entry><entry><title type="html">EF Migrations Database Script deployment Azure DevOps</title><link href="https://vandsh.github.io/azure/2020/09/30/ef-migration-script-devops.html" rel="alternate" type="text/html" title="EF Migrations Database Script deployment Azure DevOps" /><published>2020-09-30T00:00:00+00:00</published><updated>2020-09-30T00:00:00+00:00</updated><id>https://vandsh.github.io/azure/2020/09/30/ef-migration-script-devops</id><content type="html" xml:base="https://vandsh.github.io/azure/2020/09/30/ef-migration-script-devops.html"><![CDATA[<p>Working on a recent project that has a small database to store data for post processing, we turned to <a href="https://docs.microsoft.com/en-us/ef/core/">ef for dotnet core</a>.  We used a <code class="language-plaintext highlighter-rouge">code-first</code> approach and leveraged <code class="language-plaintext highlighter-rouge">migrations</code>. The only last piece we had to figure out is how to have these changes make it to our servers via <code class="language-plaintext highlighter-rouge">DevOps</code>.</p>

<p>Thankfully there is a nice little <code class="language-plaintext highlighter-rouge">cli</code> for ef; <a href="https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet"><code class="language-plaintext highlighter-rouge">dotnet-ef</code></a>.  The cli made it easy to include new migrations/features into the project and also help us facilitate getting those changes out into the wild.  Below are a few of the commands and snippets we used to accomplish this:</p>

<h2 id="basic-usage">Basic usage</h2>

<p>Below covers just some of the basic cli commands to get up and running.</p>

<h3 id="installing-dotnet-ef">Installing dotnet-ef</h3>

<p>Pretty basic, but just getting it installed for use later…</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dotnet</span><span class="w"> </span><span class="nx">tool</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nt">--global</span><span class="w"> </span><span class="nx">dotnet-ef</span><span class="w">
</span></code></pre></div></div>

<h3 id="adding-a-migration">Adding a migration</h3>

<p>Adding a new migration; could be a new “feature” or a set of significant changes</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dotnet</span><span class="w"> </span><span class="nx">ef</span><span class="w"> </span><span class="nx">migrations</span><span class="w"> </span><span class="nx">add</span><span class="w"> </span><span class="nx">FeatureName</span><span class="w">
</span></code></pre></div></div>

<h3 id="updating-database">Updating database</h3>

<p>This command will actually update the database that is part of the current project, given the current migration files.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dotnet</span><span class="w"> </span><span class="nx">ef</span><span class="w"> </span><span class="nx">database</span><span class="w"> </span><span class="nx">update</span><span class="w"> </span><span class="nt">--project</span><span class="w"> </span><span class="o">.</span><span class="nx">\src\YourProject.csproj</span><span class="w">
</span></code></pre></div></div>

<h2 id="devops-usage">DevOps usage</h2>

<p>Assuming you are now at a point where you have your migrations in source and are ready to deploy, below should help guide you thru getting those changes out onto servers.</p>

<h3 id="create-a-migration-script">Create a migration script</h3>

<p>After all your standard dotnet core build tasks, add a <code class="language-plaintext highlighter-rouge">powershell</code> task like so:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="pi">-</span> <span class="na">task</span><span class="pi">:</span> <span class="s">PowerShell@2</span>
  <span class="na">inputs</span><span class="pi">:</span>
    <span class="na">targetType</span><span class="pi">:</span> <span class="s1">'</span><span class="s">inline'</span>
    <span class="na">script</span><span class="pi">:</span> <span class="pi">|</span>
      <span class="s">dotnet tool install --global dotnet-ef</span>
      <span class="s">dotnet ef migrations script --idempotent --project $(Build.SourcesDirectory)\src\YourProject.csproj --output $(Build.ArtifactStagingDirectory)/db.sql</span>
 
</code></pre></div></div>

<p>What the above does is install the <code class="language-plaintext highlighter-rouge">dotnet-ef</code> cli within the context of the hosted agent and then use it to create a single script to encompass all the migration changes. As you can see we specify the <code class="language-plaintext highlighter-rouge">--project</code>, the <code class="language-plaintext highlighter-rouge">--output</code> folder so it gets picked up by the <code class="language-plaintext highlighter-rouge">publishBuildArtifacts</code> task and a <code class="language-plaintext highlighter-rouge">--idempotent</code> flag. The <code class="language-plaintext highlighter-rouge">--idempotent</code> flag encompasses all changes with a check to the <code class="language-plaintext highlighter-rouge">__EFMigrationsHistory</code> to see what version of migration it is on, thus allowing you to both create from scratch and iterate over an existing database with the same script:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">IF</span> <span class="k">NOT</span> <span class="k">EXISTS</span><span class="p">(</span><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="p">[</span><span class="n">__EFMigrationsHistory</span><span class="p">]</span> <span class="k">WHERE</span> <span class="p">[</span><span class="n">MigrationId</span><span class="p">]</span> <span class="o">=</span> <span class="n">N</span><span class="s1">'20200923211638_InitialCreate'</span><span class="p">)</span>
</code></pre></div></div>

<p>Now that we have a single script that can handle all things database schema, let’s make sure the release is capable of executing this.</p>

<h3 id="deploy-database-changes-in-release">Deploy database changes in Release</h3>

<p>Assuming you are at a point where all your web assets are already being deployed successfully, let’s find the <code class="language-plaintext highlighter-rouge">SQL Server database deploy</code> task. Search for it by name in the task search and add it to your release.  This task is able to deploy <code class="language-plaintext highlighter-rouge">dacpac</code> files as well as <code class="language-plaintext highlighter-rouge">sql</code> scripts, we will be using the latter. After adding the task, populate it using the following:</p>

<ul>
  <li>Deploy SQL using: <code class="language-plaintext highlighter-rouge">Sql Query File</code></li>
  <li>Sql File: <code class="language-plaintext highlighter-rouge">$(System.DefaultWorkingDirectory)\_YourProject\drop\db.sql</code></li>
  <li>Execute within a transaction: <code class="language-plaintext highlighter-rouge">true</code></li>
  <li>Server Name: <code class="language-plaintext highlighter-rouge">&lt;the sql server instance, with respect to where your release agent is running&gt;</code></li>
  <li>Database Name: <code class="language-plaintext highlighter-rouge">NameOfYourDatabase</code>
    <ul>
      <li>Make sure the database at exists</li>
      <li>If using <code class="language-plaintext highlighter-rouge">Windows Authentication</code>, make sure the user that the release agent runs as has access to this database.</li>
    </ul>
  </li>
</ul>

<p>Send it.</p>

<p>You should now be able to encompass all your database changes in source control, generate a change script that respects the database version and effectively deploy those changes to the database.</p>

<p>Enjoy!</p>]]></content><author><name></name></author><category term="Azure" /><category term="Azure" /><category term="EF" /><category term="DevOps" /><summary type="html"><![CDATA[Working on a recent project that has a small database to store data for post processing, we turned to ef for dotnet core. We used a code-first approach and leveraged migrations. The only last piece we had to figure out is how to have these changes make it to our servers via DevOps.]]></summary></entry><entry><title type="html">Azure API Management: Webhook Signature Validation</title><link href="https://vandsh.github.io/azure/2020/04/09/apim-webhook-validation.html" rel="alternate" type="text/html" title="Azure API Management: Webhook Signature Validation" /><published>2020-04-09T00:00:00+00:00</published><updated>2020-04-09T00:00:00+00:00</updated><id>https://vandsh.github.io/azure/2020/04/09/apim-webhook-validation</id><content type="html" xml:base="https://vandsh.github.io/azure/2020/04/09/apim-webhook-validation.html"><![CDATA[<p>Recently working on a handful of <a href="https://azure.microsoft.com/en-us/services/api-management/">Azure API Management</a> efforts, we came across an interesting one: an operation being triggered from a <a href="https://developer.github.com/webhooks/creating/">GitHub</a> event, triggered as a webhook. My first instinct was to look and see if anything similar to the <a href="https://docs.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies#ValidateJWT"><code class="language-plaintext highlighter-rouge">validate-jwt</code></a> token was available as a policy, but alas, it was not. So, instead I feel back to what I know best: code.</p>

<p>Ultimately in order to validate this webhook, we needed to know the following:</p>
<ul>
  <li>The header (or query parameter) that the signature was being stuffed in</li>
  <li>The secret that was being used to create the signature</li>
</ul>

<p>If we know that, we can</p>
<ul>
  <li>create the signature, given the payload of the body</li>
  <li>can compare the signatures</li>
  <li>pass or fail the request based on comparison</li>
</ul>

<h2 id="webhook-signature-verification-policy">Webhook Signature Verification Policy</h2>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;policies&gt;</span>
    <span class="nt">&lt;inbound&gt;</span>
        <span class="nt">&lt;base</span> <span class="nt">/&gt;</span>
        <span class="c">&lt;!-- Grab the signature from the header and stuff it in a variable --&gt;</span>
        <span class="nt">&lt;set-variable</span> <span class="na">name=</span><span class="s">"requestSignature"</span> <span class="na">value=</span><span class="s">"@{
            return context.Request.Headers["</span><span class="err">X-Hub-Signature"][0].Replace("</span><span class="na">sha1=</span><span class="s">","</span><span class="err">");</span>
            <span class="err">}"</span> <span class="nt">/&gt;</span>
        <span class="c">&lt;!-- Take the payload and the Secret (which should be in a KeyVault or at least a secret Named value) 
            and generate a hash to compare to the original.--&gt;</span>
        <span class="nt">&lt;set-variable</span> <span class="na">name=</span><span class="s">"compareHash"</span> <span class="na">value=</span><span class="s">"@{
            byte[] keyByte = System.Text.ASCIIEncoding.ASCII.GetBytes("</span><span class="err">NotASecret!");</span>
            <span class="err">byte[]</span> <span class="na">messageBytes =</span> <span class="s">System.Text.ASCIIEncoding.ASCII.GetBytes(context.Request.Body.As&lt;string</span><span class="nt">&gt;</span>());
            var hash = new HMACSHA1(keyByte);
            var hashBytes = hash.ComputeHash(messageBytes);
            StringBuilder hex = new StringBuilder(hashBytes.Length * 2);
            foreach (byte b in hashBytes){
                hex.AppendFormat("{0:x2}", b);
            }
            return (string)hex.ToString();
        }" /&gt;
        <span class="nt">&lt;choose&gt;</span>
            <span class="c">&lt;!-- Cast as strings and comapare the signature/hashes --&gt;</span>
            <span class="nt">&lt;when</span> <span class="na">condition=</span><span class="s">"@((string)context.Variables["</span><span class="err">requestSignature"]</span> <span class="err">!=</span> <span class="err">(string)context.Variables["compareHash"])"</span><span class="nt">&gt;</span>
                <span class="c">&lt;!-- The return response stops all further processing and in this case returns a 401 --&gt;</span>
                <span class="nt">&lt;return-response&gt;</span>
                    <span class="nt">&lt;set-status</span> <span class="na">code=</span><span class="s">"401"</span> <span class="na">reason=</span><span class="s">"Not Authorized"</span> <span class="nt">/&gt;</span>
                    <span class="c">&lt;!-- Uncomment if you need to debug --&gt;</span>
                    <span class="c">&lt;!-- &lt;set-body template="none"&gt;@{
                        return context.Variables["requestSignature"] + "::" + context.Variables["compareHash"];
                    }&lt;/set-body&gt; --&gt;</span>
                <span class="nt">&lt;/return-response&gt;</span>
            <span class="nt">&lt;/when&gt;</span>
            <span class="nt">&lt;otherwise&gt;</span>
                <span class="nt">&lt;set-backend-service</span> <span class="na">base-url=</span><span class="s">"http://yourbackend.service/notreal/"</span> <span class="nt">/&gt;</span>
            <span class="nt">&lt;/otherwise&gt;</span>
        <span class="nt">&lt;/choose&gt;</span>
    <span class="nt">&lt;/inbound&gt;</span>
    <span class="c">&lt;!-- The backend and outbound nodes, ie: the rest of the stuff --&gt;</span>
<span class="nt">&lt;/policies&gt;</span>
</code></pre></div></div>

<p>Thru the variables and then the <code class="language-plaintext highlighter-rouge">choose/when</code> condition, we can short circuit any invalid signatures before going any further and in the event it <em>is valid</em>, the body of the original request will continue to the <code class="language-plaintext highlighter-rouge">backend-service</code> url for further processing. In this case it was a repository that handled resource orchestration on an internal network (Ansible, Puppet or Chef I don’t recall which).</p>

<p>This is just one of many ways that <code class="language-plaintext highlighter-rouge">Azure APIM</code> can prove it’s power and flexibility!</p>

<p>PS: Anyone looking for a way to “sanity check” or simply test the validation logic of the policy, check out the <a href="https://www.postman.com/vandsh/workspace/dev-blog-examples/collection/2227242-d6ae589f-9059-4b5a-a5b3-ef0b395853b6?action=share&amp;creator=2227242">Postman collection here</a>. Before anything, swap out the <code class="language-plaintext highlighter-rouge">baseurl</code>, <code class="language-plaintext highlighter-rouge">apimsubscriptionkey</code> and <code class="language-plaintext highlighter-rouge">secret</code> Collection variables to meet your needs. Then, swing over to the <code class="language-plaintext highlighter-rouge">Pre-request Scripts</code> to see exactly how the entire signature is generated.</p>]]></content><author><name></name></author><category term="Azure" /><category term="Azure" /><category term="APIM" /><category term="Webhook" /><summary type="html"><![CDATA[Recently working on a handful of Azure API Management efforts, we came across an interesting one: an operation being triggered from a GitHub event, triggered as a webhook. My first instinct was to look and see if anything similar to the validate-jwt token was available as a policy, but alas, it was not. So, instead I feel back to what I know best: code.]]></summary></entry><entry><title type="html">NuGet for Website Projects</title><link href="https://vandsh.github.io/dotnet/2020/04/08/website-proj-nuget.html" rel="alternate" type="text/html" title="NuGet for Website Projects" /><published>2020-04-08T00:00:00+00:00</published><updated>2020-04-08T00:00:00+00:00</updated><id>https://vandsh.github.io/dotnet/2020/04/08/website-proj-nuget</id><content type="html" xml:base="https://vandsh.github.io/dotnet/2020/04/08/website-proj-nuget.html"><![CDATA[<h3 id="the-problem">The Problem</h3>
<p>Unlike proper <code class="language-plaintext highlighter-rouge">Web Application</code> projects, <code class="language-plaintext highlighter-rouge">Website</code> projects in Visual Studio just take everything under a folder and assume that is the project. And 9 times out of 10 (based on the handful of times I have dealt with them) these projects, when in source control, have <em>all</em> binaries checked in as well.</p>

<p>References can be sorta made using <code class="language-plaintext highlighter-rouge">NuGet</code> on the <code class="language-plaintext highlighter-rouge">Bin</code> folder, but in my experience this only sort-of works: <code class="language-plaintext highlighter-rouge">.refresh</code> files are added to the folder as a kind of redirect to the original file located elsewhere (like the <code class="language-plaintext highlighter-rouge">../packages</code> directory. These refreshes are triggered at certain times like when the project is opened or switching between projects. It also does not care about any folders nested underneath like the <code class="language-plaintext highlighter-rouge">Bin/roslyn</code> folder.</p>

<p>That kinda stinks.</p>

<h3 id="the-solution">The Solution</h3>
<p>A single Powershell file to help facilitate the restore and frankly, copying of dlls locally so we can work without having to shove binary files in source.
In addition to the script, I also included a custom <code class="language-plaintext highlighter-rouge">nuget.config</code> to allow for other <code class="language-plaintext highlighter-rouge">NuGet</code> feeds (like <code class="language-plaintext highlighter-rouge">Telerik</code>).</p>

<p>Folder Structure:</p>
<ul>
  <li>Project/ (root)
    <ul>
      <li>.nuget/nuget.config</li>
      <li>lib/</li>
      <li>packages/</li>
      <li>src/</li>
      <li>restore.ps1</li>
    </ul>
  </li>
</ul>

<h2 id="nugetnugetconfig">.nuget/nuget.config</h2>

<p>Make sure we have all the dependencies we need, in our case we needed <code class="language-plaintext highlighter-rouge">Telerik</code> as well, which happens to be authenticated.</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="nt">&lt;configuration&gt;</span>
  <span class="nt">&lt;packageSources&gt;</span>
    <span class="nt">&lt;add</span> <span class="na">key=</span><span class="s">"Telerik"</span> <span class="na">value=</span><span class="s">"https://nuget.telerik.com/nuget"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;add</span> <span class="na">key=</span><span class="s">"nuget.org"</span> <span class="na">value=</span><span class="s">"https://api.nuget.org/v3/index.json"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;/packageSources&gt;</span>
  <span class="nt">&lt;activePackageSource&gt;</span>
    <span class="nt">&lt;add</span> <span class="na">key=</span><span class="s">"All"</span> <span class="na">value=</span><span class="s">"(Aggregate source)"</span> <span class="nt">/&gt;</span>
  <span class="nt">&lt;/activePackageSource&gt;</span>
  <span class="nt">&lt;packageSourceCredentials&gt;</span>
    <span class="nt">&lt;Telerik&gt;</span>
      <span class="nt">&lt;add</span> <span class="na">key=</span><span class="s">"Username"</span> <span class="na">value=</span><span class="s">"bob@pizza.co"</span> <span class="nt">/&gt;</span>
      <span class="nt">&lt;add</span> <span class="na">key=</span><span class="s">"ClearTextPassword"</span> <span class="na">value=</span><span class="s">"NoToppings!"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/Telerik&gt;</span>
  <span class="nt">&lt;/packageSourceCredentials&gt;</span>
<span class="nt">&lt;/configuration&gt;</span>
</code></pre></div></div>

<h2 id="restoreps1">restore.ps1</h2>

<p>Handle what the package manager in a website project can’t:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">set-location</span><span class="w"> </span><span class="bp">$PSScriptRoot</span><span class="w">
</span><span class="n">Write-Host</span><span class="w"> </span><span class="s2">"Executing NuGet self update and restore"</span><span class="w"> </span><span class="nt">-ForegroundColor</span><span class="w"> </span><span class="nx">Green</span><span class="w">
</span><span class="n">nuget</span><span class="w"> </span><span class="nx">update</span><span class="w"> </span><span class="nt">-self</span><span class="w">
</span><span class="n">nuget</span><span class="w"> </span><span class="nx">restore</span><span class="w"> </span><span class="o">.</span><span class="nx">\src\packages.config</span><span class="w">  </span><span class="nt">-PackagesDirectory</span><span class="w"> </span><span class="nx">packages</span><span class="w">

</span><span class="n">set-location</span><span class="w"> </span><span class="bp">$PSScriptRoot</span><span class="nx">\src</span><span class="w">
</span><span class="n">Write-Host</span><span class="w"> </span><span class="s2">"Copying files for .refresh"</span><span class="w"> </span><span class="nt">-ForegroundColor</span><span class="w"> </span><span class="nx">Green</span><span class="w">
</span><span class="n">Get-ChildItem</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="o">.</span><span class="nx">/</span><span class="w"> </span><span class="nt">-Filter</span><span class="w"> </span><span class="o">*.</span><span class="nf">refresh</span><span class="w"> </span><span class="nt">-Recurse</span><span class="w"> </span><span class="nt">-File</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">ForEach-Object</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nv">$referenceFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Get-Content</span><span class="w"> </span><span class="bp">$_</span><span class="w">
    </span><span class="nv">$destinationFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">$_</span><span class="o">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s2">".refresh"</span><span class="p">,</span><span class="w"> </span><span class="s2">""</span><span class="p">)</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="nv">$referenceFile</span><span class="w"> </span><span class="s2">" -&gt; "</span><span class="w">   </span><span class="nv">$destinationFile</span><span class="w">
    </span><span class="n">Copy-Item</span><span class="w"> </span><span class="nv">$referenceFile</span><span class="w"> </span><span class="nt">-Destination</span><span class="w"> </span><span class="nv">$destinationFile</span><span class="w">
</span><span class="p">}</span><span class="w">

</span></code></pre></div></div>

<p>Executing this script does the following:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">NuGet</code> self update</li>
  <li><code class="language-plaintext highlighter-rouge">NuGet</code> restore using the <code class="language-plaintext highlighter-rouge">packages.config</code> maintained by the project and puts them one layer up in the <code class="language-plaintext highlighter-rouge">../packages</code> directory</li>
  <li>Iterates thru all of the <code class="language-plaintext highlighter-rouge">.refresh</code> files in the project and copies over the original <code class="language-plaintext highlighter-rouge">*.dll</code> file to the location of the <code class="language-plaintext highlighter-rouge">.refresh</code> file.</li>
</ul>

<p>This helped a lot for local development, particularly for the initial environment setups.  Queue the next step…</p>

<h2 id="cicd">CI/CD</h2>

<p>Along with this effort, we also helped set up <code class="language-plaintext highlighter-rouge">CI/CD</code> within <code class="language-plaintext highlighter-rouge">Azure Devops</code>. We used a very similar principle in resolving the dependencies during the Build pipeline:</p>

<ul>
  <li>Use NuGet 5.5.0 task</li>
  <li>NuGet restore task
    <ul>
      <li>Path to NuGet.config <code class="language-plaintext highlighter-rouge">$/Project/.nuget/nuget.config</code></li>
      <li>Destination Directory <code class="language-plaintext highlighter-rouge">$(UserProfile)/.nuget/packages</code></li>
    </ul>
  </li>
  <li>PowerShell Script task (inline)
    <ul>
      <li>
        <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Write-Host</span><span class="w"> </span><span class="bp">$PSScriptRoot</span><span class="w">
</span><span class="n">Write-Host</span><span class="w"> </span><span class="s2">"Copying files for .refresh"</span><span class="w"> </span><span class="nt">-ForegroundColor</span><span class="w"> </span><span class="nx">Green</span><span class="w">
</span><span class="n">Get-ChildItem</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="o">.</span><span class="nx">/</span><span class="w"> </span><span class="nt">-Filter</span><span class="w"> </span><span class="o">*.</span><span class="nf">refresh</span><span class="w"> </span><span class="nt">-Recurse</span><span class="w"> </span><span class="nt">-File</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">ForEach-Object</span><span class="w"> </span><span class="p">{</span><span class="w">
 </span><span class="nv">$referenceFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Get-Content</span><span class="w"> </span><span class="bp">$_</span><span class="p">)</span><span class="o">.</span><span class="nf">Replace</span><span class="p">(</span><span class="s2">"..\packages"</span><span class="p">,</span><span class="s2">"</span><span class="si">$(</span><span class="n">UserProfile</span><span class="p">)</span><span class="n">\.nuget\packages</span><span class="s2">")
 </span><span class="nv">$destinationFile</span><span class="s2"> = </span><span class="bp">$_</span><span class="s2">.Replace("</span><span class="o">.</span><span class="nf">refresh</span><span class="s2">", "")
 Write-Host </span><span class="nv">$referenceFile</span><span class="s2"> "</span><span class="w"> </span><span class="o">-</span><span class="err">&gt;</span><span class="w"> </span><span class="s2">"   </span><span class="nv">$destinationFile</span><span class="s2">
 Copy-Item </span><span class="nv">$referenceFile</span><span class="s2"> -Destination </span><span class="nv">$destinationFile</span><span class="s2">
}

</span></code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li>Build Solution task</li>
  <li>Solution: <code class="language-plaintext highlighter-rouge">$/Project/src/website.publishproj</code></li>
  <li>MSBuild Arguments
    <ul>
      <li><code class="language-plaintext highlighter-rouge">/p:deployOnBuild=true</code></li>
      <li><code class="language-plaintext highlighter-rouge">/p:publishProfile=Project</code></li>
      <li><code class="language-plaintext highlighter-rouge">/p:publishUrl="$(build.artifactstagingdirectory)\\"</code></li>
    </ul>
  </li>
  <li>Publish Artifacts task</li>
</ul>

<p>The result of the above pipeline and really the entire effort is a solution that doesn’t involve checking in binaries, uses NuGet and overall feels just slightly closer to normal Web Application development.</p>

<p>Hope this helps!</p>]]></content><author><name></name></author><category term="dotnet" /><category term="dotnet" /><category term="NuGet" /><category term="CI-CD" /><category term="Powershell" /><summary type="html"><![CDATA[The Problem Unlike proper Web Application projects, Website projects in Visual Studio just take everything under a folder and assume that is the project. And 9 times out of 10 (based on the handful of times I have dealt with them) these projects, when in source control, have all binaries checked in as well.]]></summary></entry><entry><title type="html">Bridge: YAML CI for Kentico</title><link href="https://vandsh.github.io/kentico/2020/03/19/kentico-bridge.html" rel="alternate" type="text/html" title="Bridge: YAML CI for Kentico" /><published>2020-03-19T00:00:00+00:00</published><updated>2020-03-19T00:00:00+00:00</updated><id>https://vandsh.github.io/kentico/2020/03/19/kentico-bridge</id><content type="html" xml:base="https://vandsh.github.io/kentico/2020/03/19/kentico-bridge.html"><![CDATA[<p>Having worked in Kentico for a while, something that keeps coming up in the back of my mind is: why hasn’t someone developed a friendly tool to manage the database items? I was looking for something using YAML so it’s easy to merge and use in source control, completely free and open-source, config driven and (last but not least) able to be leveraged in a dev-ops workflow.</p>

<p>Ultimately I wanted something like <a href="https://github.com/SitecoreUnicorn/Unicorn">SitecoreUnicorn</a> but for Kentico. In my quest to find this tool, I didn’t find many that checked all these req’s so I decided to just start throwing things at a wall to see what stuck. After some dev effort and show and tell with colleagues, I have what I consider not even a <code class="language-plaintext highlighter-rouge">beta</code> solution yet.</p>

<p>Let me introduce to you <code class="language-plaintext highlighter-rouge">Bridge</code> for Kentico!</p>

<h1 id="---bridge">-|–|- Bridge</h1>

<p><a href="https://github.com/vandsh/bridge">Github Repository</a></p>

<p><img src="/assets/bridgescreenshot.png" alt="alt text" title="Bridge Screenshot" /></p>

<h2 id="the-what">The what?</h2>
<ul>
  <li>A Yaml based service for handling the promotion of Kentico CMS based items thru source control.</li>
</ul>

<h2 id="the-why">The why?</h2>
<ul>
  <li>Because XML is terrible to read and even harder to merge. The reason I created this was to allow us to not only break down features modularly thru some basic configs, but I wanted to make sure it was easy to adopt and that means making it easy to use with source control.</li>
</ul>

<h2 id="the-when">The when?</h2>
<ul>
  <li>Use this either along side an existing Kentico build using the <a href="https://www.nuget.org/packages/Bridge.Kentico/">nuget</a> or standalone by cloning this repo and updating the <code class="language-plaintext highlighter-rouge">connectionString</code> parameters to match your Kentico db.</li>
</ul>

<h2 id="the-how">The how?</h2>
<ul>
  <li>Installation:
    <ul>
      <li><em>Standalone</em>: clone, compile and run the app. Fire up a browser and go to <code class="language-plaintext highlighter-rouge">localhost/bridge/index</code></li>
      <li><em>Alongside</em>: install via <a href="https://www.nuget.org/packages/Bridge.Kentico/">nuget</a> and navigate to <code class="language-plaintext highlighter-rouge">yourKenticoUrl/Admin/BridgeUI/index</code></li>
    </ul>
  </li>
  <li>The configs:
    <ul>
      <li><em>CoreConfig</em>: one or more core config can be specified. They contain a list of <code class="language-plaintext highlighter-rouge">classtypes</code> to care about and a list of <code class="language-plaintext highlighter-rouge">ignoreFields</code> on the item to simply ignore when serializing/syncing.</li>
      <li><em>ContentConfig</em>: one or more content config can be specified. Contains a list of <code class="language-plaintext highlighter-rouge">pagetypes</code> to care about and a list of <code class="language-plaintext highlighter-rouge">ignoreFields</code> on the items to not serialize/sync. This also will handle all custom fields. Also, a <code class="language-plaintext highlighter-rouge">query</code> attribute allows you to pick which content within the tree to focus on. This should support a basic Kentico Query.</li>
    </ul>
  </li>
  <li>Using the GUI:
    <ul>
      <li>Core Configs:
        <ul>
          <li>Core Configs <em>Serialize All</em>: iterates thru all of the defined <code class="language-plaintext highlighter-rouge">coreConfig</code> nodes and fetches all the corresponding classes, and stuffs them into the <code class="language-plaintext highlighter-rouge">serialization/core/{coreConfigName}</code> folder.</li>
          <li>Core Configs <em>Sync All</em>: this is the inverse of the <code class="language-plaintext highlighter-rouge">Serialize All</code> task, it takes what’s in the file system and pushes it to the Kentico DB.</li>
          <li>“Named Core Config” <em>Serialize</em>: pulls <em>just</em> the specified config down to the file system</li>
          <li>“Named Core Config” <em>Sync</em>: pushes <em>just</em> the specified config up to the database</li>
          <li>“Named Core Config” <em>Diff</em>: does a temp serialize of the current Kentico DB and compares it to what’s in the filesystem and spits out a diff.</li>
        </ul>
      </li>
      <li>Content Configs:
        <ul>
          <li>Content Configs <em>Serialize All</em>: iterates thru all of the defined <code class="language-plaintext highlighter-rouge">contentConfig</code> nodes and fetches all the corresponding classes, and stuffs them into the <code class="language-plaintext highlighter-rouge">serialization/content/{contentConfigName}</code> folder.</li>
          <li>Content Configs <em>Sync All</em>: this is the inverse of the <code class="language-plaintext highlighter-rouge">Serialize All</code> task, it takes what’s in the file system and pushes it to the Kentico DB.</li>
          <li>“Named Content Config” <em>Serialize</em>: pulls <em>just</em> the specified config down to the file system</li>
          <li>“Named Content Config” <em>Sync</em>: pushes <em>just</em> the specified config up to the database</li>
          <li>“Named Content Config” <em>Diff</em>: does a temp serialize of the current Kentico DB and compares it to what’s in the filesystem and spits out a diff.</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>The Endpoints:
    <ul>
      <li>Within a dev-ops cycle (ie a release to a dev or test environment) make a call to the Bridge endpoints using an authenticated call (using something like <code class="language-plaintext highlighter-rouge">curl</code>, <code class="language-plaintext highlighter-rouge">wget</code> or <code class="language-plaintext highlighter-rouge">Invoke-WebRequest</code>).</li>
      <li>The response itself should be a stream so it will respond as things occur rather than processing everything and responding.</li>
      <li>The endpoints are as follows:
        <ul>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/diffcore?/{configName}</code>: returns the comparison between the serialized DB and what is in the file system for the optional core configName</li>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/diffcontent?/{configName}</code>: returns the comparison between the serialized DB and what is in the file system for the optional content configName</li>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/serializecore?/{configName}</code>: serializes the specified core config (or all if none specified) to the filesystem</li>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/serializecontent?/{configName}</code>: serializes the specified content config (or all if none specified) to the filesystem</li>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/synccore?/{configName}</code>: syncs the specified core config (or all if none specified) to the database</li>
          <li><code class="language-plaintext highlighter-rouge">yourUrl/bridge/synccontent?/{configName}</code>: syncs the specified content config (or all if none specified) to the database</li>
        </ul>
      </li>
      <li><em>My ultimate goal is to leverage the endpoints in order to promote a continuous integration and deployment methodology within the Kentico community</em></li>
    </ul>
  </li>
</ul>

<h2 id="the-dev-questions">The dev questions?</h2>
<ul>
  <li>What kind of Class Types do the <code class="language-plaintext highlighter-rouge">CoreConfigs</code> include?
    <ul>
      <li>Any custom class you create in Kentico should be covered: page types, custom tables etc.</li>
    </ul>
  </li>
  <li>What are the <code class="language-plaintext highlighter-rouge">ignoreFields</code>?
    <ul>
      <li>Fields that we are just going to ignore, either they are tied to users, sites, timestamps or other content.</li>
      <li>We strip them so we can insert the content cleanly without reference to the originating source site.</li>
    </ul>
  </li>
  <li>What fields do <code class="language-plaintext highlighter-rouge">ContentConfigs</code> include?
    <ul>
      <li>Anything not in the <code class="language-plaintext highlighter-rouge">ignoreFields</code> should be written to YAML.</li>
      <li>This includes custom fields.</li>
    </ul>
  </li>
  <li>Security?
    <ul>
      <li>Bridge actually ties into the Kentico membership provider.</li>
      <li>Standalone: Using the NancyFx Basic Auth provider, it forwards the basic auth creds into the Kentico Provider to validate you are a user.</li>
      <li>Alongside: it picks up the <code class="language-plaintext highlighter-rouge">HttpContext.CurrentUser.IsAuthenticated</code> from your logged in Kentico session.</li>
      <li>Security wise, this is really just checking to make sure you are <em>an authenticated user, nothing more</em>, but we could in the future check for roles or claims.</li>
      <li>If installing this in (eventually) a staging or production environment, you may want to consider using it only during the release process and then (programmatically) deleting the <code class="language-plaintext highlighter-rouge">/Bridge</code> folder and/or removing the <code class="language-plaintext highlighter-rouge">NancyHttpRequestHandler</code> entry in the <code class="language-plaintext highlighter-rouge">web.config</code></li>
    </ul>
  </li>
  <li>Why <a href="https://github.com/NancyFx/Nancy">Nancy</a>?
    <ul>
      <li>Low-ceremony dependency injection: so I could see about making this tool more universal</li>
      <li>Lightweight and self-contained: I don’t know how people want to use this tool: standalone, alongside kentico?</li>
      <li>Simple request control: I didn’t want to have to worry about the routes someone was using in their Kentico site.</li>
    </ul>
  </li>
  <li>Why YAML?
    <ul>
      <li>Easy to read, easy to merge. I wanted to defer as much of this process to standard tooling like merging item conflicts using Kdiff/WinMerge etc.</li>
      <li>Smaller file footprint: I didn’t need all of the wrapper XML nodes.</li>
    </ul>
  </li>
  <li>Future plans?
    <ul>
      <li>Please feel free to hit me up if you like the tool but are having issues or would like to see any new features</li>
      <li>If you feel inclined to contribute, forks and pull requests are always welcomed.</li>
      <li>One thing I have already kinda planned for is allowing for multi-site configs, allowing you to handle different sites all within one GUI.</li>
      <li>I have also considered abstracting out the Kentico libraries and making this into a tool that could handle a raw database as well, time will tell.</li>
    </ul>
  </li>
</ul>

<h2 id="disclaimer">Disclaimer</h2>

<p>This is in alpha for a reason: it’s incredibly green and raw. I am hoping over time it ages like a fine wine. 
With that said, use at your own risk until you are comfortable with the changes you are making.</p>

<p>Anyways, thanks for reading!</p>]]></content><author><name></name></author><category term="Kentico" /><category term="Kentico" /><category term="Deploy" /><category term="CI-CD" /><summary type="html"><![CDATA[Having worked in Kentico for a while, something that keeps coming up in the back of my mind is: why hasn’t someone developed a friendly tool to manage the database items? I was looking for something using YAML so it’s easy to merge and use in source control, completely free and open-source, config driven and (last but not least) able to be leveraged in a dev-ops workflow.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://vandsh.github.io/assets/bridgelogo.png" /><media:content medium="image" url="https://vandsh.github.io/assets/bridgelogo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Custom Tag Helpers in dotnet MVC</title><link href="https://vandsh.github.io/dotnet/2019/10/31/mvc-tag-helper.html" rel="alternate" type="text/html" title="Custom Tag Helpers in dotnet MVC" /><published>2019-10-31T00:00:00+00:00</published><updated>2019-10-31T00:00:00+00:00</updated><id>https://vandsh.github.io/dotnet/2019/10/31/mvc-tag-helper</id><content type="html" xml:base="https://vandsh.github.io/dotnet/2019/10/31/mvc-tag-helper.html"><![CDATA[<p>Ok, so every project you come across, especially when you get people logging in with various roles and responsibilities, you eventually get the request to have things conditionally show or hide based on those roles. Traditionally, I would have just used some good old <code class="language-plaintext highlighter-rouge">if</code> statements in the <code class="language-plaintext highlighter-rouge">View</code> (what fun is that). I poked around for a cooler solution and came across <a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-3.0"><code class="language-plaintext highlighter-rouge">Tag Helpers</code></a>.</p>

<p>I had seen this before: <code class="language-plaintext highlighter-rouge">&lt;a class="nav-link" asp-controller="Account" asp-action="SignOut"&gt;Logout&lt;/a&gt;</code> so I thought it was worth a try. What I wanted was a way to explicitly hide or show a menu item, a button, a link or any DOM element really for certain users.</p>

<p>Since I already had the user and role management pieces sorted out, and some <code class="language-plaintext highlighter-rouge">constants</code> for these roles, I figured I could pass them in to my <code class="language-plaintext highlighter-rouge">tag helper</code> to denote which one(s) to show or hide for.</p>

<h2 id="permissionconstantscs">PermissionConstants.cs</h2>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">PermissionConstants</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">Job</span>
    <span class="p">{</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Create</span> <span class="p">=</span> <span class="s">"JobCreate"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Read</span> <span class="p">=</span> <span class="s">"JobRead"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Update</span> <span class="p">=</span> <span class="s">"JobUpdate"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Deactivate</span> <span class="p">=</span> <span class="s">"JobDeactivate"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">User</span>
    <span class="p">{</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Create</span> <span class="p">=</span> <span class="s">"UserCreate"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Read</span> <span class="p">=</span> <span class="s">"UserRead"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Update</span> <span class="p">=</span> <span class="s">"UserUpdate"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">Deactivate</span> <span class="p">=</span> <span class="s">"UserDeactivate"</span><span class="p">;</span>
        <span class="k">public</span> <span class="k">const</span> <span class="kt">string</span> <span class="n">ManageRoles</span> <span class="p">=</span> <span class="s">"UserManageRoles"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The above <code class="language-plaintext highlighter-rouge">roles</code> were associated with a user and acquired by doing a <code class="language-plaintext highlighter-rouge">_userService.GetCurrentUserPermissionsAsync()</code>, of course with some proper caching so we weren’t hammering a database with every instance of the tag helper.</p>

<h2 id="showfortaghelpercs">ShowForTagHelper.cs</h2>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nf">HtmlTargetElement</span><span class="p">(</span><span class="n">Attributes</span><span class="p">=</span><span class="s">"show-for-permission"</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">HtmlTargetElement</span><span class="p">(</span><span class="n">Attributes</span><span class="p">=</span><span class="s">"hide-for-permission"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ShowForTagHelper</span> <span class="p">:</span> <span class="n">TagHelper</span>
<span class="p">{</span>
    <span class="k">private</span> <span class="k">readonly</span> <span class="n">IUserService</span> <span class="n">_userService</span><span class="p">;</span>
    <span class="k">public</span> <span class="nf">ShowForTagHelper</span><span class="p">(</span><span class="n">IUserService</span> <span class="n">userService</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">_userService</span> <span class="p">=</span> <span class="n">userService</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">/// &lt;summary&gt;</span>
    <span class="c1">/// Show this html element for a particular permission type</span>
    <span class="c1">/// &lt;/summary&gt;</span>
    <span class="p">[</span><span class="nf">HtmlAttributeName</span><span class="p">(</span><span class="s">"show-for-permission"</span><span class="p">)]</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="n">ShowForPermission</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>

    <span class="c1">/// &lt;summary&gt;</span>
    <span class="c1">/// Hide this html element for a particular permission type</span>
    <span class="c1">/// &lt;/summary&gt;</span>
    <span class="p">[</span><span class="nf">HtmlAttributeName</span><span class="p">(</span><span class="s">"hide-for-permission"</span><span class="p">)]</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="n">HideForPermission</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="k">override</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">ProcessAsync</span><span class="p">(</span><span class="n">TagHelperContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">TagHelperOutput</span> <span class="n">output</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">base</span><span class="p">.</span><span class="nf">Process</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">output</span><span class="p">);</span>
        <span class="kt">var</span> <span class="n">currentUserPermissionsAll</span> <span class="p">=</span> <span class="k">await</span> <span class="n">_userService</span><span class="p">.</span><span class="nf">CurrentUserPermissionsAsync</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">currentUserPermissionsAll</span> <span class="p">!=</span> <span class="k">null</span> <span class="p">&amp;&amp;</span> <span class="n">currentUserPermissionsAll</span><span class="p">.</span><span class="nf">Any</span><span class="p">())</span>
        <span class="p">{</span>
            <span class="kt">var</span> <span class="n">currentUserPermissions</span> <span class="p">=</span> <span class="n">currentUserPermissionsAll</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Value</span><span class="p">).</span><span class="nf">Select</span><span class="p">(</span><span class="n">p</span> <span class="p">=&gt;</span> <span class="n">p</span><span class="p">.</span><span class="n">Key</span><span class="p">);</span>
            <span class="kt">bool</span> <span class="n">showForUser</span> <span class="p">=</span> <span class="p">(</span><span class="n">ShowForPermission</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">?</span> <span class="n">currentUserPermissions</span>
				<span class="p">.</span><span class="nf">Intersect</span><span class="p">(</span><span class="nf">_getPermissionsList</span><span class="p">(</span><span class="n">ShowForPermission</span><span class="p">)).</span><span class="nf">Any</span><span class="p">()</span> <span class="p">:</span> <span class="k">true</span><span class="p">;</span>
            <span class="kt">bool</span> <span class="n">hideForUser</span> <span class="p">=</span> <span class="p">(</span><span class="n">HideForPermission</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">?</span> <span class="n">currentUserPermissions</span>
				<span class="p">.</span><span class="nf">Intersect</span><span class="p">(</span><span class="nf">_getPermissionsList</span><span class="p">(</span><span class="n">HideForPermission</span><span class="p">)).</span><span class="nf">Any</span><span class="p">()</span> <span class="p">:</span> <span class="k">false</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(!</span><span class="n">showForUser</span> <span class="p">||</span> <span class="n">hideForUser</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">output</span><span class="p">.</span><span class="nf">SuppressOutput</span><span class="p">();</span>
                <span class="c1">//since at this point the output is suppressed, it doesn't pay to continue checking...</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">else</span>
        <span class="p">{</span>
	    <span class="c1">// if attribute exists, but user has no roles: hide</span>
            <span class="n">output</span><span class="p">.</span><span class="nf">SuppressOutput</span><span class="p">();</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">private</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;</span> <span class="nf">_getPermissionsList</span><span class="p">(</span><span class="kt">string</span> <span class="n">permAttr</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">permAttr</span><span class="p">.</span><span class="nf">Split</span><span class="p">(</span><span class="sc">','</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>A quick unpacking of the above:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">_userService</code> is injected into the constuctor</li>
  <li>two distinct attributes defined
    <ul>
      <li><code class="language-plaintext highlighter-rouge">HtmlTargetElement</code> decorator associates the attributes to the helper</li>
      <li><code class="language-plaintext highlighter-rouge">HtmlAttributeName</code> associates the attributes to to concrete properties</li>
    </ul>
  </li>
  <li>override the <code class="language-plaintext highlighter-rouge">ProcessAsync</code> method to do your thing
    <ul>
      <li><code class="language-plaintext highlighter-rouge">output.SuppressOutput()</code> is the magic that hides this from ever being rendered</li>
    </ul>
  </li>
</ul>

<p>The last thing we need to do before we actually use this in markup is to register the namespace in the <code class="language-plaintext highlighter-rouge">_ViewImports.cshtml</code>:</p>
<h2 id="viewimportscshtml">ViewImports.cshtml</h2>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">@using</span> <span class="n">YourNamespace</span>
<span class="n">@using</span> <span class="n">StackExchange</span><span class="p">.</span><span class="n">Profiling</span>
<span class="n">@addTagHelper</span> <span class="p">*,</span> <span class="n">MiniProfiler</span><span class="p">.</span><span class="n">AspNetCore</span><span class="p">.</span><span class="n">Mvc</span>
<span class="n">@addTagHelper</span> <span class="p">*,</span> <span class="n">Microsoft</span><span class="p">.</span><span class="n">AspNetCore</span><span class="p">.</span><span class="n">Mvc</span><span class="p">.</span><span class="n">TagHelpers</span>
<span class="n">@addTagHelper</span> <span class="p">*,</span> <span class="n">SmartBreadcrumbs</span>
<span class="n">@addTagHelper</span> <span class="p">*,</span> <span class="n">YourNamespace</span><span class="p">.</span><span class="n">Helpers</span>
</code></pre></div></div>

<p>Yes, I know, there are a few other <code class="language-plaintext highlighter-rouge">tag helpers</code> registered, but for good reason: I love the <code class="language-plaintext highlighter-rouge">MiniProfiler</code> and use it on my local/dev/test instances as a sanity check and the <code class="language-plaintext highlighter-rouge">SmartBreadcrumbs</code> is handy for generating a breadcrumb nav by <code class="language-plaintext highlighter-rouge">controller</code> and <code class="language-plaintext highlighter-rouge">action</code> auto-magically..</p>

<h2 id="somemarkupcshtml">SomeMarkup.cshtml</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- other markup, then an action link that only shows for people who have 
		the roles needed to view or update a Job --&gt;</span>

<span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">"nav-link"</span> <span class="na">asp-area=</span><span class="s">""</span> <span class="na">asp-controller=</span><span class="s">"Jobs"</span> <span class="na">asp-action=</span><span class="s">"Index"</span> 
<span class="na">show-for-permission=</span><span class="s">"@(PermissionConstants.Jobs.Read +"</span><span class="err">,"+</span><span class="na">PermissionConstants.Jobs.Update</span><span class="err">)"</span><span class="nt">&gt;</span>Profile<span class="nt">&lt;/a&gt;</span>

<span class="c">&lt;!-- more arbitrary markup, then an entire div hidden based on role --&gt;</span>

<span class="nt">&lt;div</span> <span class="na">show-for-permission=</span><span class="s">"@(PermissionConstants.User.Read +"</span><span class="err">,"+</span><span class="na">PermissionConstants.User.Update</span><span class="err">)"</span><span class="nt">&gt;</span>
    <span class="c">&lt;!-- cool things only a user with User read/update perms can see or do --&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>Hopefully the above shows you a real world case for using a custom <code class="language-plaintext highlighter-rouge">TagHelper</code>. Not only does it seem pretty clean and heavily reusable, but honestly it feels like it separates the concern of hiding or showing content based on a users permissions to a separate handler (almost AOP-esq, don’t quote me on that tho!).</p>]]></content><author><name></name></author><category term="dotnet" /><category term="dotnet" /><category term="MVC" /><category term="ASP.Net" /><summary type="html"><![CDATA[Ok, so every project you come across, especially when you get people logging in with various roles and responsibilities, you eventually get the request to have things conditionally show or hide based on those roles. Traditionally, I would have just used some good old if statements in the View (what fun is that). I poked around for a cooler solution and came across Tag Helpers.]]></summary></entry><entry><title type="html">Testing Webhooks or B2C Policies using Azure Functions</title><link href="https://vandsh.github.io/azure/2019/07/22/azure-function-webhook.html" rel="alternate" type="text/html" title="Testing Webhooks or B2C Policies using Azure Functions" /><published>2019-07-22T00:00:00+00:00</published><updated>2019-07-22T00:00:00+00:00</updated><id>https://vandsh.github.io/azure/2019/07/22/azure-function-webhook</id><content type="html" xml:base="https://vandsh.github.io/azure/2019/07/22/azure-function-webhook.html"><![CDATA[<p>This post is going to be an incredibly short and sweet post covering the ability to test things like <code class="language-plaintext highlighter-rouge">Webhooks</code> or <code class="language-plaintext highlighter-rouge">Azure B2C</code> policies. If you are familiar with either, you will already know they require a generally publicly accessible service running in order to process the request. In my partuclar case, creating an invitation  <code class="language-plaintext highlighter-rouge">Policy</code> within <code class="language-plaintext highlighter-rouge">Azure B2C</code>, I wanted to trigger a “Welcome” email from this policy, but really had no clue how the <code class="language-plaintext highlighter-rouge">Claims</code> or request headers came across. So I used what I knew: I created an <code class="language-plaintext highlighter-rouge">Azure Function</code> that would grab all the things of the request and email it to me.</p>

<p>In this case, I want a simple <code class="language-plaintext highlighter-rouge">Http Triggered</code> function with with <code class="language-plaintext highlighter-rouge">Function</code> auth level and supported <code class="language-plaintext highlighter-rouge">GET|POST</code> http methods. I gave it a name (<code class="language-plaintext highlighter-rouge">WebhookPayloadEmail</code>), dropped the below code in the <code class="language-plaintext highlighter-rouge">run.csx</code> and added entries for <code class="language-plaintext highlighter-rouge">SmtpServer</code>, <code class="language-plaintext highlighter-rouge">SmtpUserName</code> and <code class="language-plaintext highlighter-rouge">SmtpPassword</code> to the <code class="language-plaintext highlighter-rouge">Application Settings</code> of the <code class="language-plaintext highlighter-rouge">Function App</code> itself. 
Once done with all that, I ran it a few times locally to make sure it compiled, threw a few arbitrary values in the query, headers and request body to make sure they all got caught and once I confirmed that working, I figured we were ready to go and grabbed the <code class="language-plaintext highlighter-rouge">Function</code> url (<code class="language-plaintext highlighter-rouge">&lt;/&gt; Get function URL</code>).</p>

<h2 id="webhookpayloademail-function">WebhookPayloadEmail Function</h2>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">#</span><span class="n">r</span> <span class="s">"Newtonsoft.Json"</span>

<span class="k">using</span> <span class="nn">System.Net</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.AspNetCore.Mvc</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Microsoft.Extensions.Primitives</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">Newtonsoft.Json</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Net.Mail</span><span class="p">;</span>

<span class="k">public</span> <span class="k">static</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="n">IActionResult</span><span class="p">&gt;</span> <span class="nf">Run</span><span class="p">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="p">,</span> <span class="n">ILogger</span> <span class="n">log</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">log</span><span class="p">.</span><span class="nf">LogInformation</span><span class="p">(</span><span class="s">"C# HTTP trigger function processed a request."</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">smtpHost</span> <span class="p">=</span> <span class="nf">GetEnvironmentVariable</span><span class="p">(</span><span class="s">"SmtpServer"</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">smtpPort</span> <span class="p">=</span> <span class="m">587</span><span class="p">;</span>
    <span class="kt">var</span> <span class="n">smtpEnableSsl</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
    <span class="kt">var</span> <span class="n">smtpUser</span> <span class="p">=</span> <span class="nf">GetEnvironmentVariable</span><span class="p">(</span><span class="s">"SmtpUserName"</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">smtpPass</span> <span class="p">=</span> <span class="nf">GetEnvironmentVariable</span><span class="p">(</span><span class="s">"SmtpPassword"</span><span class="p">);</span>
    <span class="kt">string</span> <span class="n">requestBody</span> <span class="p">=</span> <span class="k">await</span> <span class="k">new</span> <span class="nf">StreamReader</span><span class="p">(</span><span class="n">req</span><span class="p">.</span><span class="n">Body</span><span class="p">).</span><span class="nf">ReadToEndAsync</span><span class="p">();</span>
    <span class="kt">string</span> <span class="n">serializedQuery</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="nf">SerializeObject</span><span class="p">(</span><span class="n">req</span><span class="p">.</span><span class="n">Query</span><span class="p">);</span>
    <span class="kt">string</span> <span class="n">seralizedHeader</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="nf">SerializeObject</span><span class="p">(</span><span class="n">req</span><span class="p">.</span><span class="n">Headers</span><span class="p">);</span>

    <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">SmtpClient</span><span class="p">(</span><span class="n">smtpHost</span><span class="p">,</span> <span class="n">smtpPort</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">client</span><span class="p">.</span><span class="n">UseDefaultCredentials</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
        <span class="n">client</span><span class="p">.</span><span class="n">Credentials</span> <span class="p">=</span> <span class="k">new</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="nf">NetworkCredential</span><span class="p">(</span><span class="n">smtpUser</span><span class="p">,</span> <span class="n">smtpPass</span><span class="p">);</span>
        <span class="n">client</span><span class="p">.</span><span class="n">DeliveryMethod</span> <span class="p">=</span> <span class="n">SmtpDeliveryMethod</span><span class="p">.</span><span class="n">Network</span><span class="p">;</span>
        <span class="n">client</span><span class="p">.</span><span class="n">EnableSsl</span> <span class="p">=</span> <span class="n">smtpEnableSsl</span><span class="p">;</span>
        <span class="n">MailMessage</span> <span class="n">message</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">MailMessage</span><span class="p">(</span><span class="s">"from@test.test"</span><span class="p">,</span> <span class="s">"to@test.test"</span><span class="p">);</span>
        <span class="n">message</span><span class="p">.</span><span class="n">Subject</span> <span class="p">=</span> <span class="s">"Test Submission"</span><span class="p">;</span>
        <span class="n">message</span><span class="p">.</span><span class="n">IsBodyHtml</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
        <span class="n">message</span><span class="p">.</span><span class="n">Body</span> <span class="p">=</span> <span class="n">requestBody</span> <span class="p">+</span> <span class="s">"\n\n"</span> <span class="p">+</span> <span class="n">serializedQuery</span> <span class="p">+</span> <span class="s">"\n\n"</span> <span class="p">+</span> <span class="n">seralizedHeader</span><span class="p">;</span>
        
        <span class="k">try</span>
        <span class="p">{</span>
            <span class="n">client</span><span class="p">.</span><span class="nf">Send</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
            <span class="n">log</span><span class="p">.</span><span class="nf">LogInformation</span><span class="p">(</span><span class="s">"Success."</span><span class="p">);</span>
            

            <span class="k">return</span> <span class="p">(</span><span class="n">ActionResult</span><span class="p">)</span><span class="k">new</span> <span class="nf">OkObjectResult</span><span class="p">(</span>
                <span class="k">new</span> <span class="p">{</span>
                    <span class="n">status</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span>
                    <span class="n">message</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Empty</span>
                <span class="p">});</span>
        <span class="p">}</span>
        <span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">ex</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">log</span><span class="p">.</span><span class="nf">LogError</span><span class="p">(</span><span class="s">"Failure: "</span> <span class="p">+</span> <span class="n">ex</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
            <span class="k">return</span> <span class="k">new</span> <span class="nf">BadRequestObjectResult</span><span class="p">(</span><span class="k">new</span>
                <span class="p">{</span>
                    <span class="n">status</span> <span class="p">=</span> <span class="k">false</span><span class="p">,</span>
                    <span class="n">message</span> <span class="p">=</span> <span class="s">"Check Azure Function Logs for more information."</span>
                <span class="p">});</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">static</span> <span class="kt">string</span> <span class="nf">GetEnvironmentVariable</span><span class="p">(</span><span class="kt">string</span> <span class="n">name</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">Environment</span><span class="p">.</span><span class="nf">GetEnvironmentVariable</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">EnvironmentVariableTarget</span><span class="p">.</span><span class="n">Process</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Above is the main guts of this post but to round things out, in my <code class="language-plaintext highlighter-rouge">Azure B2C</code> scenario, I created a <code class="language-plaintext highlighter-rouge">ClaimsProvider</code> (see below) to trigger on the last <code class="language-plaintext highlighter-rouge">OrchestrationStep</code> of the <code class="language-plaintext highlighter-rouge">Invitation</code> of the invitation <code class="language-plaintext highlighter-rouge">UserJourney</code>:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;ClaimsProvider&gt;</span>
    <span class="nt">&lt;DisplayName&gt;</span>Azure Functions<span class="nt">&lt;/DisplayName&gt;</span>
    <span class="nt">&lt;TechnicalProfiles&gt;</span>
        <span class="c">&lt;!-- The following technical profile sends a mail message to a user. --&gt;</span>
        <span class="nt">&lt;TechnicalProfile</span> <span class="na">Id=</span><span class="s">"AzureFunctions-SendMailWebHook"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;DisplayName&gt;</span>Send Mail Web Hook Azure Function<span class="nt">&lt;/DisplayName&gt;</span>
            <span class="nt">&lt;Protocol</span> <span class="na">Name=</span><span class="s">"Proprietary"</span> <span class="na">Handler=</span><span class="s">"Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"</span> <span class="nt">/&gt;</span>
            <span class="nt">&lt;Metadata&gt;</span>
                <span class="nt">&lt;Item</span> <span class="na">Key=</span><span class="s">"ServiceUrl"</span><span class="nt">&gt;</span>https://yourtenant.azurewebsites.net/api/WebhookPayloadEmail?code=T4Isi2N0tAR3L1C0D3==<span class="nt">&lt;/Item&gt;</span>
                <span class="nt">&lt;Item</span> <span class="na">Key=</span><span class="s">"AuthenticationType"</span><span class="nt">&gt;</span>None<span class="nt">&lt;/Item&gt;</span>
                <span class="nt">&lt;Item</span> <span class="na">Key=</span><span class="s">"SendClaimsIn"</span><span class="nt">&gt;</span>Body<span class="nt">&lt;/Item&gt;</span>
                <span class="nt">&lt;Item</span> <span class="na">Key=</span><span class="s">"AllowInsecureAuthInProduction"</span><span class="nt">&gt;</span>true<span class="nt">&lt;/Item&gt;</span>
            <span class="nt">&lt;/Metadata&gt;</span>
            <span class="nt">&lt;InputClaims&gt;</span>
                <span class="nt">&lt;InputClaim</span> <span class="na">ClaimTypeReferenceId=</span><span class="s">"objectId"</span> <span class="nt">/&gt;</span>
                <span class="c">&lt;!--&lt;InputClaim ClaimTypeReferenceId="anotherValue" PartnerClaimType="claimNameInPayload" /&gt;--&gt;</span>
            <span class="nt">&lt;/InputClaims&gt;</span>
            <span class="nt">&lt;UseTechnicalProfileForSessionManagement</span> <span class="na">ReferenceId=</span><span class="s">"SM-Noop"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;/TechnicalProfile&gt;</span>
    <span class="nt">&lt;/TechnicalProfiles&gt;</span>
<span class="nt">&lt;/ClaimsProvider&gt;</span>
</code></pre></div></div>

<p>And there you have it, an <code class="language-plaintext highlighter-rouge">Azure Function</code> that could funcition as a <code class="language-plaintext highlighter-rouge">Webhook</code> recipient or a <code class="language-plaintext highlighter-rouge">ServiceUrl</code> for an <code class="language-plaintext highlighter-rouge">Azure B2C Policy</code>!</p>

<p><em>I realize this discusses the Azure Function more than Azure B2C, but after a little bit of headache and following <a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-get-started-custom">this tutorial</a> and <a href="https://github.com/Azure-Samples/active-directory-b2c-advanced-policies/tree/master/wingtipgamesb2c">this codebase</a> pretty closely, I found Azure B2C to be extremely powerful for handling authentication (just in case you stumble on this page looking for help on B2C and not Azure Functions)…</em></p>

<p>&lt;/message&gt;</p>]]></content><author><name></name></author><category term="Azure" /><category term="Azure" /><category term="Webhooks" /><category term="B2C" /><summary type="html"><![CDATA[This post is going to be an incredibly short and sweet post covering the ability to test things like Webhooks or Azure B2C policies. If you are familiar with either, you will already know they require a generally publicly accessible service running in order to process the request. In my partuclar case, creating an invitation Policy within Azure B2C, I wanted to trigger a “Welcome” email from this policy, but really had no clue how the Claims or request headers came across. So I used what I knew: I created an Azure Function that would grab all the things of the request and email it to me.]]></summary></entry><entry><title type="html">Dependency Injection in Kentico</title><link href="https://vandsh.github.io/kentico/2019/06/21/kentico-di.html" rel="alternate" type="text/html" title="Dependency Injection in Kentico" /><published>2019-06-21T00:00:00+00:00</published><updated>2019-06-21T00:00:00+00:00</updated><id>https://vandsh.github.io/kentico/2019/06/21/kentico-di</id><content type="html" xml:base="https://vandsh.github.io/kentico/2019/06/21/kentico-di.html"><![CDATA[<p>If you have been in development long enough you have likely heard of <a href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> and also are familiar with some of the benefitial side effects like testability, reuseability/replaceability and overall code quality.  When developing a <em>custom development</em> solution your options are pretty endless, but when you are working within a CMS based solution like Kentico you usually are confined to the bounds of the framework.  Thankfully, Kentico’s services <a href="https://docs.kentico.com/k12/developing-websites/initializing-kentico-services-with-dependency-injection">are injectable</a> which means if done correctly, you shouldn’t have to initialize your calls to out-of-box services but instead be lazy (like me) and have them be injected.</p>

<p>For the sake of this blog post, I am going to try and lay out the base implementation details needed to both inject the Kentico services and your own custom ones. Our solution will be Kentico 12 using <a href="https://www.nuget.org/packages/Autofac.Mvc5">Autofac</a> as our DI container. Before anything, we must get the application to pick up and register the services at application start:</p>

<h3 id="dependencyinjectionconfigcs">DependencyInjectionConfig.cs</h3>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">YourNamespace.App_Start</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">DependencyInjectionConfig</span>
    <span class="p">{</span>
        <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">RegisterDependencies</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="c1">// Initializes the Autofac builder instance</span>
            <span class="kt">var</span> <span class="n">builder</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ContainerBuilder</span><span class="p">();</span>

            <span class="c1">// Adds a custom registration source (IRegistrationSource) that registers Kentico Services</span>
            <span class="n">builder</span><span class="p">.</span><span class="nf">RegisterSource</span><span class="p">(</span><span class="k">new</span> <span class="nf">CMSRegistrationSource</span><span class="p">());</span>
            <span class="n">builder</span><span class="p">.</span><span class="nf">RegisterControllers</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">MvcApplication</span><span class="p">).</span><span class="n">Assembly</span><span class="p">);</span>

            <span class="c1">// Find all `Service` classes by their interface and resolve the attribute/class types</span>
            <span class="kt">var</span> <span class="n">serviceIntefaces</span> <span class="p">=</span> <span class="n">Assembly</span><span class="p">.</span><span class="nf">GetExecutingAssembly</span><span class="p">().</span><span class="nf">GetTypes</span><span class="p">()</span>
					<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">IsInterface</span> <span class="p">&amp;&amp;</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">.</span><span class="nf">EndsWith</span><span class="p">(</span><span class="s">"Service"</span><span class="p">));</span>

            <span class="kt">var</span> <span class="n">serviceClasses</span> <span class="p">=</span> <span class="n">Assembly</span><span class="p">.</span><span class="nf">GetExecutingAssembly</span><span class="p">().</span><span class="nf">GetTypes</span><span class="p">()</span>
					<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="p">!</span><span class="n">x</span><span class="p">.</span><span class="n">IsInterface</span> <span class="p">&amp;&amp;</span> <span class="n">x</span><span class="p">.</span><span class="n">Name</span><span class="p">.</span><span class="nf">EndsWith</span><span class="p">(</span><span class="s">"Service"</span><span class="p">))</span>
					<span class="p">.</span><span class="nf">Select</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> 
					    <span class="k">new</span> <span class="n">ServiceRegistration</span> <span class="p">{</span> 
					        <span class="n">Service</span> <span class="p">=</span> <span class="n">x</span><span class="p">,</span> 
					        <span class="n">Interface</span> <span class="p">=</span> <span class="n">x</span><span class="p">.</span><span class="nf">GetInterfaces</span><span class="p">().</span><span class="nf">FirstOrDefault</span><span class="p">(</span><span class="n">i</span> <span class="p">=&gt;</span> <span class="n">serviceIntefaces</span><span class="p">.</span><span class="nf">Contains</span><span class="p">(</span><span class="n">i</span><span class="p">))</span> 
					    <span class="p">});</span>
            
	    <span class="c1">// Find all Service that is assignable from IService and register them</span>
            <span class="k">foreach</span><span class="p">(</span><span class="kt">var</span> <span class="n">serviceClass</span> <span class="k">in</span> <span class="n">serviceClasses</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span> <span class="n">x</span><span class="p">.</span><span class="n">Interface</span> <span class="p">!=</span> <span class="k">null</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">builder</span><span class="p">.</span><span class="nf">RegisterType</span><span class="p">(</span><span class="n">serviceClass</span><span class="p">.</span><span class="n">Service</span><span class="p">).</span><span class="nf">As</span><span class="p">(</span><span class="n">serviceClass</span><span class="p">.</span><span class="n">Interface</span><span class="p">);</span>
            <span class="p">}</span>

            <span class="c1">// Autowire Property Injection for controllers (in case they aren't using constructor injection)</span>
            <span class="kt">var</span> <span class="n">allControllers</span> <span class="p">=</span> <span class="n">Assembly</span><span class="p">.</span><span class="nf">GetExecutingAssembly</span><span class="p">().</span><span class="nf">GetTypes</span><span class="p">()</span>
					<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">type</span> <span class="p">=&gt;</span> <span class="k">typeof</span><span class="p">(</span><span class="n">BaseController</span><span class="p">).</span><span class="nf">IsAssignableFrom</span><span class="p">(</span><span class="n">type</span><span class="p">));</span>
            <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">controller</span> <span class="k">in</span> <span class="n">allControllers</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">builder</span><span class="p">.</span><span class="nf">RegisterType</span><span class="p">(</span><span class="n">controller</span><span class="p">).</span><span class="nf">PropertiesAutowired</span><span class="p">();</span>
            <span class="p">}</span>

            <span class="c1">// Resolves the dependencies</span>
            <span class="kt">var</span> <span class="n">container</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="nf">Build</span><span class="p">();</span>
            <span class="n">DependencyResolver</span><span class="p">.</span><span class="nf">SetResolver</span><span class="p">(</span><span class="k">new</span> <span class="nf">AutofacDependencyResolver</span><span class="p">(</span><span class="n">container</span><span class="p">));</span>

            <span class="kt">var</span> <span class="n">allRegs</span> <span class="p">=</span> <span class="n">container</span><span class="p">.</span><span class="n">ComponentRegistry</span><span class="p">.</span><span class="n">Registrations</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">class</span> <span class="nc">ServiceRegistration</span>
    <span class="p">{</span>
        <span class="k">public</span> <span class="n">Type</span> <span class="n">Service</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
        <span class="k">public</span> <span class="n">Type</span> <span class="n">Interface</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">class</span> <span class="nc">CMSRegistrationSource</span> <span class="p">:</span> <span class="n">IRegistrationSource</span>
    <span class="p">{</span>
        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Gets whether the registrations provided by this source are 1:1 adapters on top of other components (I.e. like Meta, Func or Owned.)</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="k">public</span> <span class="kt">bool</span> <span class="n">IsAdapterForIndividualComponents</span> <span class="p">=&gt;</span> <span class="k">false</span><span class="p">;</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Retrieves registrations for an unregistered service, to be used by the container.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="service"&gt;The service that was requested.&lt;/param&gt;</span>
        <span class="c1">/// &lt;param name="registrationAccessor"&gt;A function that will return existing registrations for a service.&lt;/param&gt;</span>
        <span class="k">public</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">IComponentRegistration</span><span class="p">&gt;</span> <span class="nf">RegistrationsFor</span><span class="p">(</span><span class="n">Service</span> <span class="n">service</span><span class="p">,</span> <span class="n">Func</span><span class="p">&lt;</span><span class="n">Service</span><span class="p">,</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">IComponentRegistration</span><span class="p">&gt;&gt;</span> <span class="n">registrationAccessor</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="c1">// Checks whether the container already contains an existing registration for the requested service</span>
            <span class="k">if</span> <span class="p">(</span><span class="nf">registrationAccessor</span><span class="p">(</span><span class="n">service</span><span class="p">).</span><span class="nf">Any</span><span class="p">())</span>
            <span class="p">{</span>
                <span class="k">return</span> <span class="n">Enumerable</span><span class="p">.</span><span class="n">Empty</span><span class="p">&lt;</span><span class="n">IComponentRegistration</span><span class="p">&gt;();</span>
            <span class="p">}</span>

            <span class="c1">// Checks that the requested service carries valid type information</span>
            <span class="kt">var</span> <span class="n">swt</span> <span class="p">=</span> <span class="n">service</span> <span class="k">as</span> <span class="n">IServiceWithType</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">swt</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">return</span> <span class="n">Enumerable</span><span class="p">.</span><span class="n">Empty</span><span class="p">&lt;</span><span class="n">IComponentRegistration</span><span class="p">&gt;();</span>
            <span class="p">}</span>

            <span class="c1">// Gets an instance of the requested service using the CMS.Core API</span>
            <span class="kt">object</span> <span class="n">instance</span> <span class="p">=</span> <span class="k">null</span><span class="p">;</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">CMS</span><span class="p">.</span><span class="n">Core</span><span class="p">.</span><span class="n">Service</span><span class="p">.</span><span class="nf">IsRegistered</span><span class="p">(</span><span class="n">swt</span><span class="p">.</span><span class="n">ServiceType</span><span class="p">))</span>
            <span class="p">{</span>
                <span class="n">instance</span> <span class="p">=</span> <span class="n">CMS</span><span class="p">.</span><span class="n">Core</span><span class="p">.</span><span class="n">Service</span><span class="p">.</span><span class="nf">Resolve</span><span class="p">(</span><span class="n">swt</span><span class="p">.</span><span class="n">ServiceType</span><span class="p">);</span>
            <span class="p">}</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">instance</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="k">return</span> <span class="n">Enumerable</span><span class="p">.</span><span class="n">Empty</span><span class="p">&lt;</span><span class="n">IComponentRegistration</span><span class="p">&gt;();</span>
            <span class="p">}</span>

            <span class="c1">// Registers the service instance in the container</span>
            <span class="k">return</span> <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">RegistrationBuilder</span><span class="p">.</span><span class="nf">ForDelegate</span><span class="p">(</span><span class="n">swt</span><span class="p">.</span><span class="n">ServiceType</span><span class="p">,</span> <span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="n">instance</span><span class="p">).</span><span class="nf">CreateRegistration</span><span class="p">()</span> <span class="p">};</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now let’s invoke the config class to register those <code class="language-plaintext highlighter-rouge">Services</code> at startup:</p>

<h3 id="globalasaxcs">Global.asax.cs</h3>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">YourNamespace</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">MvcApplication</span> <span class="p">:</span> <span class="n">HttpApplication</span>
    <span class="p">{</span>
        <span class="k">protected</span> <span class="k">void</span> <span class="nf">Application_Start</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="c1">// Register services both CMS and custom</span>
            <span class="n">DependencyInjectionConfig</span><span class="p">.</span><span class="nf">RegisterDependencies</span><span class="p">();</span>

	    <span class="c1">/// ... all the other things</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The above will do two very key things:</p>

<ul>
  <li>Register all <code class="language-plaintext highlighter-rouge">Kentico Services</code> for injection</li>
  <li>Register all custom <code class="language-plaintext highlighter-rouge">Services</code> we create
    <ul>
      <li>This keys specficially on naming conventions, if you have a <code class="language-plaintext highlighter-rouge">Service</code> end it with the word <code class="language-plaintext highlighter-rouge">Service</code>. <code class="language-plaintext highlighter-rouge">ExampleService</code> will implement <code class="language-plaintext highlighter-rouge">IExampleService</code> (below).</li>
    </ul>
  </li>
</ul>

<p>Doing this on <code class="language-plaintext highlighter-rouge">Application_Start</code> will take a little time on initial load, but no time during runtime.</p>

<p>Alright, let’s go over an example of a service. Below will be a service <code class="language-plaintext highlighter-rouge">Interface</code> with an <code class="language-plaintext highlighter-rouge">Implementation</code>:</p>

<h3 id="iexampleservicecs">IExampleService.cs</h3>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">YourNamespace.Services.Interfaces</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">interface</span> <span class="nc">IExampleService</span>
    <span class="p">{</span>
        <span class="n">ITreeNode</span> <span class="nf">GetCurrentNode</span><span class="p">();</span>
        <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">SubNav</span><span class="p">&gt;</span> <span class="nf">GetSubNavFromAliasPath</span><span class="p">(</span><span class="kt">string</span> <span class="n">nodeAliasPath</span><span class="p">,</span> <span class="n">CultureInfo</span> <span class="n">cultureInfo</span><span class="p">,</span> <span class="n">ISiteInfo</span> <span class="n">siteInfo</span> <span class="p">=</span> <span class="k">null</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="exampleservicecs">ExampleService.cs</h3>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">YourNamespace.Services.Implementation</span>
<span class="p">{</span>
    <span class="c1">/// &lt;summary&gt;</span>
    <span class="c1">/// This class is an example of how to use Dependency Injection to get common classes and services without having instantiating them on your own.</span>
    <span class="c1">/// Some high level reasons that may prove useful: reusability/replaceability (forces modular development)</span>
    <span class="c1">/// and testability (you can mock interfaces in order to properly test your written code)</span>
    <span class="c1">/// &lt;/summary&gt;</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">ExampleService</span> <span class="p">:</span> <span class="n">IExampleService</span>
    <span class="p">{</span>
        <span class="c1">// Below are Kentico classes that are coded to an intercace and can be injected via Constructor Injection</span>
        <span class="k">public</span> <span class="n">ISiteService</span> <span class="n">_siteService</span><span class="p">;</span>
        <span class="k">public</span> <span class="n">IEventLogService</span> <span class="n">_eventLogService</span><span class="p">;</span>
        <span class="k">public</span> <span class="n">IHttpContextAccessor</span> <span class="n">_httpContextAccessor</span><span class="p">;</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Any parameters in the signature should be injected via constructor injection, </span>
        <span class="c1">/// if invoking this service direclty you will need to instantiate your own</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="siteService"&gt;&lt;/param&gt;</span>
        <span class="c1">/// &lt;param name="eventLogService"&gt;&lt;/param&gt;</span>
        <span class="c1">/// &lt;param name="httpContextAccessor"&gt;&lt;/param&gt;</span>
        <span class="k">public</span> <span class="nf">ExampleService</span><span class="p">(</span><span class="n">ISiteService</span> <span class="n">siteService</span><span class="p">,</span> <span class="n">IEventLogService</span> <span class="n">eventLogService</span><span class="p">,</span> <span class="n">IHttpContextAccessor</span> <span class="n">httpContextAccessor</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">_siteService</span> <span class="p">=</span> <span class="n">siteService</span><span class="p">;</span>
            <span class="n">_eventLogService</span> <span class="p">=</span> <span class="n">eventLogService</span><span class="p">;</span>
            <span class="n">_httpContextAccessor</span> <span class="p">=</span> <span class="n">httpContextAccessor</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Simply gets the current node using the absolute path of the HttpContext.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="context"&gt;&lt;/param&gt;</span>
        <span class="c1">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="k">public</span> <span class="n">ITreeNode</span> <span class="nf">GetCurrentNode</span><span class="p">()</span>
        <span class="p">{</span>
	    <span class="c1">/// Using the injected _httpContextAccessor to get the request path</span>
            <span class="kt">var</span> <span class="n">absolutePath</span> <span class="p">=</span> <span class="n">_httpContextAccessor</span><span class="p">.</span><span class="n">HttpContext</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">Url</span><span class="p">.</span><span class="n">AbsolutePath</span><span class="p">;</span>
            <span class="n">ITreeNode</span> <span class="n">FoundNode</span> <span class="p">=</span> <span class="n">DocumentQueryHelper</span><span class="p">.</span><span class="nf">GetNodeByAliasPath</span><span class="p">(</span><span class="n">absolutePath</span><span class="p">);</span>
            <span class="k">return</span> <span class="n">FoundNode</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// Gets a list of `SubNav` items under the `Node` passed in.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;param name="node"&gt;&lt;/param&gt;</span>
        <span class="c1">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="k">public</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">SubNav</span><span class="p">&gt;</span> <span class="nf">GetSubNavFromAliasPath</span><span class="p">(</span><span class="kt">string</span> <span class="n">nodeAliasPath</span><span class="p">,</span> <span class="n">CultureInfo</span> <span class="n">cultureInfo</span> <span class="p">=</span> <span class="k">null</span><span class="p">,</span> <span class="n">ISiteInfo</span> <span class="n">siteInfo</span> <span class="p">=</span> <span class="k">null</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">siteInfo</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="c1">// If site is not provided, get the current site from the injected SiteService</span>
		<span class="c1">// and log (may be overkill but using it as an example)</span>
                <span class="n">siteInfo</span> <span class="p">=</span> <span class="n">_siteService</span><span class="p">.</span><span class="n">CurrentSite</span><span class="p">;</span>
                <span class="n">_eventLogService</span><span class="p">.</span><span class="nf">LogEvent</span><span class="p">(</span><span class="s">"GetSubNavFromAliasPath"</span><span class="p">,</span> <span class="s">"ExampleService"</span><span class="p">,</span> <span class="s">"GET"</span><span class="p">,</span> <span class="s">"Using current site"</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
                <span class="n">_eventLogService</span><span class="p">.</span><span class="nf">LogEvent</span><span class="p">(</span><span class="s">"GetSubNavFromAliasPath"</span><span class="p">,</span> <span class="s">"ExampleService"</span><span class="p">,</span> <span class="s">"GET"</span><span class="p">,</span> <span class="s">"Using passed in site"</span><span class="p">);</span>
            <span class="p">}</span>

            <span class="k">if</span><span class="p">(</span><span class="n">cultureInfo</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">cultureInfo</span> <span class="p">=</span> <span class="n">LocalizationContext</span><span class="p">.</span><span class="nf">GetCurrentCulture</span><span class="p">();</span>
                <span class="n">_eventLogService</span><span class="p">.</span><span class="nf">LogEvent</span><span class="p">(</span><span class="s">"GetSubNavFromAliasPath"</span><span class="p">,</span> <span class="s">"ExampleService"</span><span class="p">,</span> <span class="s">"GET"</span><span class="p">,</span> <span class="s">"Using current culture"</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
                <span class="n">_eventLogService</span><span class="p">.</span><span class="nf">LogEvent</span><span class="p">(</span><span class="s">"GetSubNavFromAliasPath"</span><span class="p">,</span> <span class="s">"ExampleService"</span><span class="p">,</span> <span class="s">"GET"</span><span class="p">,</span> <span class="s">"Using passed in culture"</span><span class="p">);</span>
            <span class="p">}</span>

            <span class="kt">var</span> <span class="n">subnavList</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="n">SubNav</span><span class="p">&gt;();</span>
            <span class="k">try</span>
            <span class="p">{</span>
                <span class="k">foreach</span> <span class="p">(</span><span class="n">ITreeNode</span> <span class="n">Node</span> <span class="k">in</span> <span class="n">DocumentQueryHelper</span><span class="p">.</span><span class="nf">RepeaterQuery</span><span class="p">(</span>
                <span class="n">Path</span><span class="p">:</span> <span class="n">nodeAliasPath</span> <span class="p">+</span> <span class="s">"/%"</span><span class="p">,</span>
                <span class="n">CultureCode</span><span class="p">:</span> <span class="n">cultureInfo</span><span class="p">.</span><span class="n">CultureCode</span><span class="p">,</span>
                <span class="n">SiteName</span><span class="p">:</span> <span class="n">siteInfo</span><span class="p">.</span><span class="n">SiteName</span><span class="p">,</span>
                <span class="n">ClassNames</span><span class="p">:</span> <span class="s">"CMS.MenuItem"</span><span class="p">,</span>
                <span class="n">OrderBy</span><span class="p">:</span> <span class="s">"NodeLevel, NodeOrder"</span><span class="p">,</span>
                <span class="n">Columns</span><span class="p">:</span> <span class="s">"MenuItemName,NodeAliasPath"</span>
                <span class="p">))</span>
                <span class="p">{</span>
                    <span class="n">subnavList</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">SubNav</span><span class="p">()</span>
                    <span class="p">{</span>
                        <span class="n">LinkText</span> <span class="p">=</span> <span class="n">Node</span><span class="p">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="s">"MenuItemName"</span><span class="p">).</span><span class="nf">ToString</span><span class="p">(),</span>
                        <span class="c1">// You have to decide what your URL will be, for us our URLs = NodeAliasPath</span>
                        <span class="n">LinkUrl</span> <span class="p">=</span> <span class="n">Node</span><span class="p">.</span><span class="n">NodeAliasPath</span>
                    <span class="p">});</span>
                <span class="p">}</span>
            <span class="p">}</span>
            <span class="k">catch</span> <span class="p">(</span><span class="n">Exception</span> <span class="n">ex</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">_eventLogService</span><span class="p">.</span><span class="nf">LogException</span><span class="p">(</span><span class="s">"ExampleService"</span><span class="p">,</span> <span class="s">"GET"</span><span class="p">,</span> <span class="n">ex</span><span class="p">);</span>
            <span class="p">}</span>
            <span class="k">return</span> <span class="n">subnavList</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Above is a trimmed down (for the sake of demonstration) version of what you will see in <a href="https://github.com/KenticoDevTrev/KenticoBoilerplate_v12">here</a>. 
Using the <code class="language-plaintext highlighter-rouge">Service</code> naming convention, we can pick it up in the <code class="language-plaintext highlighter-rouge">DependencyInjection.RegisterDependencies()</code> (line 15) method and register it with its similarly named Interface. 
I generally use this approach as a form of lazy-registering-by-naming to get off the ground fast within development, but when it comes to replace an implementation I usually will create a new <code class="language-plaintext highlighter-rouge">Service</code> and manually register it until it is fully fleshed out and then potentially rename it so it continues to get picked up by this method.</p>

<p>Now, back to the <code class="language-plaintext highlighter-rouge">ExampleService</code>, this service leverages the following <code class="language-plaintext highlighter-rouge">Kentico</code> Services:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">CMS.Base.ISiteService</code> to get the current site info</li>
  <li><code class="language-plaintext highlighter-rouge">CMS.Core.IEventLogService</code> to allow us to log events</li>
  <li><code class="language-plaintext highlighter-rouge">CMS.Base.IHttpContextAccessor</code> to access the http context</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">ExampleService</code> itself illustrates using <code class="language-plaintext highlighter-rouge">Constructor Injection</code> where already instantiated services are passed in thru the constructor. This <code class="language-plaintext highlighter-rouge">ExampleService</code> is ultimately used in a controller, <code class="language-plaintext highlighter-rouge">ExampleController</code>:</p>

<h3 id="examplecontrollercs">ExampleController.cs</h3>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="nn">YourNamespace.Controllers.Examples</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">class</span> <span class="nc">ExamplesController</span> <span class="p">:</span> <span class="n">BaseController</span>
    <span class="p">{</span>
        <span class="k">public</span> <span class="n">IExampleService</span> <span class="n">_exampleService</span><span class="p">;</span>
        <span class="k">public</span> <span class="nf">ExamplesController</span><span class="p">(</span><span class="n">IExampleService</span> <span class="n">exampleService</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="c1">// Use constructor injection to get a handle on our ExampleService</span>
            <span class="n">_exampleService</span> <span class="p">=</span> <span class="n">exampleService</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="c1">// GET: Examples</span>
        <span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">Index</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="nf">View</span><span class="p">();</span>
        <span class="p">}</span>


        <span class="c1">/// &lt;summary&gt;</span>
        <span class="c1">/// This Repeater "Webpart" Relies on just a path that would be provided through the View's context.  Does not rely on passing</span>
        <span class="c1">/// the ViewBag like the NavigationByContext, but does then require the calling View to provide the properties, and if ever more</span>
        <span class="c1">/// properties are needed, would need to adjust both Controller and View alike.</span>
        <span class="c1">/// &lt;/summary&gt;</span>
        <span class="c1">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="k">public</span> <span class="n">ActionResult</span> <span class="nf">NavigationByPath</span><span class="p">(</span><span class="kt">string</span> <span class="n">Path</span><span class="p">,</span> <span class="kt">string</span> <span class="n">Culture</span><span class="p">,</span> <span class="kt">string</span> <span class="n">SiteName</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="c1">// Build the actual Partial View's model from the data provided by the parent View</span>
            <span class="n">ExampleMVCWebPartsSubNavs</span> <span class="n">Model</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ExampleMVCWebPartsSubNavs</span><span class="p">();</span>
            <span class="c1">// Get the Sub Nav Items from the ExampleService</span>
            <span class="n">Model</span><span class="p">.</span><span class="n">SubNavigation</span> <span class="p">=</span> <span class="n">_exampleService</span><span class="p">.</span><span class="nf">GetSubNavFromAliasPath</span><span class="p">(</span><span class="n">Path</span><span class="p">,</span> <span class="n">CultureInfoProvider</span><span class="p">.</span><span class="nf">GetCultureInfo</span><span class="p">(</span><span class="n">Culture</span><span class="p">));</span>
            <span class="k">return</span> <span class="nf">View</span><span class="p">(</span><span class="s">"Navigation"</span><span class="p">,</span> <span class="n">Model</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>So at this point, we have a <code class="language-plaintext highlighter-rouge">Controller</code> with an injected dependency, <code class="language-plaintext highlighter-rouge">IExampleService</code>, that is registered at startup and that class itself uses some injected <code class="language-plaintext highlighter-rouge">Kentico</code> services. So one thing that may be apparent, this example is not perfect as some of the dependencies like <code class="language-plaintext highlighter-rouge">DocumentQueryHelper</code> are both static and not injected, but that is something we hope to have ironed out in the future.  The only thing left that I would love to illstrate and, in my opinion, is one of the biggest benefits to leveraging DI is testing (but that will have to be for a later blog post!)</p>

<p>And like I mentioned before, this is all <a href="https://github.com/KenticoDevTrev/KenticoBoilerplate_v12">publicly accessible</a> and brought to you from the beautiful Kentico minds at <a href="https://twitter.com/HBSTech">Heartland Business Sytems</a>.</p>

<p>I am hoping this post helps you put some of the pieces together on how to use <code class="language-plaintext highlighter-rouge">Dependency Injection</code> in your next <code class="language-plaintext highlighter-rouge">Kentico</code> project and reap the benefits in all their glory!</p>

<p>&lt;/message&gt;</p>]]></content><author><name></name></author><category term="Kentico" /><category term="Kentico" /><category term="DependencyInjection" /><summary type="html"><![CDATA[If you have been in development long enough you have likely heard of Dependency Injection and also are familiar with some of the benefitial side effects like testability, reuseability/replaceability and overall code quality. When developing a custom development solution your options are pretty endless, but when you are working within a CMS based solution like Kentico you usually are confined to the bounds of the framework. Thankfully, Kentico’s services are injectable which means if done correctly, you shouldn’t have to initialize your calls to out-of-box services but instead be lazy (like me) and have them be injected.]]></summary></entry></feed>