<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[I am a recent graduate at the beginning of my software developement career. I enjoy documenting my learnings through my blogs.]]></description><link>https://rachaelkeenan.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 21:49:33 GMT</lastBuildDate><atom:link href="https://rachaelkeenan.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Image recognition]]></title><description><![CDATA[This feature illustrates AI’s ability to understand and pick things out from an image using Microsoft.Extensions.AI.
This post will walk you through getting OpenAI to summarize a single image. You should end up with and output like this:

Then we wil...]]></description><link>https://rachaelkeenan.dev/image-recognition</link><guid isPermaLink="true">https://rachaelkeenan.dev/image-recognition</guid><category><![CDATA[Microsoft.Extenstions.AI]]></category><category><![CDATA[openai]]></category><category><![CDATA[.NET]]></category><category><![CDATA[C#]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Sat, 25 Jan 2025 18:25:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/km4mhtfG_H4/upload/6984fe4374e23b7430e3f12f4e7adcd4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This feature illustrates AI’s ability to understand and pick things out from an image using <code>Microsoft.Extensions.AI</code>.</p>
<p>This post will walk you through getting OpenAI to summarize a single image. You should end up with and output like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737829284187/81670a2c-cffe-4269-b7d2-19021a497444.gif" alt="AI image summarization result for a single image" class="image--center mx-auto" /></p>
<p>Then we will go a step further to extract more specific data form a set of images, aand you should see an output similar to this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737829300173/dc99948b-ad5b-47c4-8c38-3b017f438a60.gif" alt="AI image recognition result for Traffic images" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737829309944/558e3e3a-23f3-4c82-b510-9fe4c32d5969.gif" alt="AI image recognition result for Animal images" class="image--center mx-auto" /></p>
<h3 id="heading-step-1">Step 1</h3>
<p>Create a simple console app in whichever IDE you prefer.</p>
<h3 id="heading-step-2">Step 2</h3>
<p>Install the required Nuget packages and add them to the top of your <code>Program.cs</code> file:</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Package Microsoft.Extension.AI (9.1.0-preview.1.25064.3)</span>
<span class="hljs-comment">// Package Microsoft.Extensions.OpenAI (9.1.0-preview.1.25064.3)</span>
<span class="hljs-comment">// Package Microsoft.Extensions.Abstractions (9.1.0-preview.1.25064.3)</span>
<span class="hljs-comment">// Package Microsoft.Extensions.DependencyInjection (9.0.1)</span>
<span class="hljs-comment">// Package Microsoft.Extensions.Hosting (9.0.1)</span>
<span class="hljs-comment">// Package Microsoft.Extensions.Logging (9.0.1)</span>

<span class="hljs-keyword">using</span> Microsoft.Extensions.AI;
<span class="hljs-keyword">using</span> OpenAI; 
<span class="hljs-keyword">using</span> Microsoft.Extensions.Configuration;
<span class="hljs-keyword">using</span> Microsoft.Extensions.DependencyInjection;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Logging;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Hosting;
</code></pre>
<h3 id="heading-step-3">Step 3</h3>
<p>Set up the required app configurations and your AI chat completion client (<code>IChatClient</code>). I am using OpenAI for this example and I have my API key saved as an environment variable, you can change the model to whichever model you want to use.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The main aspect required here is the <code>IChatClient</code> and model you want to use. The other configurations are not required, but if you want to add extra functionality later like logging or function calling this will be needed.</div>
</div>

<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> hostBuilder = Host.CreateApplicationBuilder(args);
hostBuilder.Configuration.AddEnvironmentVariables(<span class="hljs-string">"OPENAI_API_KEY"</span>);

IChatClient innerChatClient = <span class="hljs-keyword">new</span> OpenAIClient(Environment.GetEnvironmentVariable(<span class="hljs-string">"OPENAI_API_KEY"</span>))
    .AsChatClient(<span class="hljs-string">"gpt-4o-mini"</span>);

hostBuilder.Services.AddSingleton&lt;IChatClient&gt;(innerChatClient);

hostBuilder.Services.AddLogging(builder =&gt; builder
    .AddConsole()
    .SetMinimumLevel(LogLevel.Trace));

<span class="hljs-keyword">var</span> app = hostBuilder.Build();
<span class="hljs-keyword">var</span> chatClient = app.Services.GetRequiredService&lt;IChatClient&gt;();
</code></pre>
<h3 id="heading-step-4">Step 4</h3>
<p>Set up your user message with a simple query like “What’s in this image?”.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> message = <span class="hljs-keyword">new</span> ChatMessage(ChatRole.User, <span class="hljs-string">"What's in this image?"</span>);
</code></pre>
<p>Then add your image using <code>Contents.Add</code> and add a new <code>ImageContent</code> like so:</p>
<pre><code class="lang-csharp">message.Contents.Add(<span class="hljs-keyword">new</span> ImageContent(File.ReadAllBytes(<span class="hljs-string">"&lt;path to your image"</span>),<span class="hljs-string">"image/jpg"</span>));
</code></pre>
<h3 id="heading-step-5">Step 5</h3>
<p>Once you’ve set up your user message you will need to call your chat client (OpenAI) and give it the message with the image for context.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> chatClient.CompleteAsync([message]);
</code></pre>
<p>Then write out the AI’s response to the console</p>
<pre><code class="lang-csharp">Console.WriteLine(response.Message.Text);
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If you wanted to stream the message like ChatGpt does, step 5 will look a bit different. Instead of uisng <code>CompleteAsync</code> you will use <code>CompleteStreamAsync</code> and iterate over each word (token) of the response. You will also need to use <code>Console.Write</code> for this instead of <code>Console.WriteLine</code>, as <code>WriteLine</code> will add a new line for each token.</div>
</div>

<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> responseStream = chatClient.CompleteStreamingAsync([message]);
<span class="hljs-keyword">await</span> <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> response <span class="hljs-keyword">in</span> responseStream)
{
    Console.Write(response.Text);
}
</code></pre>
<h2 id="heading-further-steps">Further Steps</h2>
<p>The above steps will be used, however step 5 will be used differently, and this will not be stream the message, as it is predefined.</p>
<h3 id="heading-step-6">Step 6</h3>
<p>Retrieve the folder of your images</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> dir = Path.Combine(AppContext.BaseDirectory, <span class="hljs-string">"&lt;path to your image folder&gt;"</span>);
</code></pre>
<h3 id="heading-step-7">Step 7</h3>
<p>Iterate over the files in the folder and select files with a specific extension, e.g. “.jpg” (this can be chnaged to whatever extension you want). The code inside the <code>foreach</code> loop will follow in Steps 8 - 11.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> imagePath <span class="hljs-keyword">in</span> Directory.GetFiles(dir, <span class="hljs-string">"*.jpg"</span>))
{
    ...
}
</code></pre>
<h3 id="heading-step-8">Step 8</h3>
<p>Get the image name without it’s extension, this will then be added to your user message</p>
<pre><code class="lang-csharp">    <span class="hljs-keyword">var</span> name = Path.GetFileNameWithoutExtension(imagePath);

    <span class="hljs-keyword">var</span> message = <span class="hljs-keyword">new</span> ChatMessage(ChatRole.User, $<span class="hljs-string">$""</span><span class="hljs-string">"
                                                   Extract information from this image from camera {{name}}.
                                                   "</span><span class="hljs-string">""</span>);
</code></pre>
<p>Adding the image file will be the same as before, but instead of passing in the full folder path you will pass in the foreach loop’s variable <code>imagePath</code></p>
<pre><code class="lang-csharp">    message.Contents.Add(<span class="hljs-keyword">new</span> ImageContent(File.ReadAllBytes(imagePath), <span class="hljs-string">"image/jpg"</span>));
</code></pre>
<h3 id="heading-step-9">Step 9</h3>
<p>Create an object class to store the relevant data</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">class</span> <span class="hljs-title">TrafficCamResult</span>
{
    <span class="hljs-keyword">public</span> TrafficStatus Status { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumCars { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumTrucks { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">enum</span> TrafficStatus
    {
        Clear,
        Flowing,
        Congested,
        Blocked
    };
}
</code></pre>
<p>Another example I did was with animals:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">class</span> <span class="hljs-title">AnimalsResult</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumAnimals { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumDogs { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumCats { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumRacoons { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumMonkeys { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumRedPandas { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> NumMeerkats { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<h3 id="heading-step-10">Step 10</h3>
<p>The above class will be used as the type parameter for the AI’s response (<code>CompleteAsync</code>), again add the user message to the chat completion.</p>
<pre><code class="lang-csharp">    <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> chatClient.CompleteAsync&lt;TrafficCamResult&gt;([message]);
</code></pre>
<h3 id="heading-step-11">Step 11</h3>
<p>Lastly get the results of the response and output them to the console.</p>
<pre><code class="lang-csharp">    <span class="hljs-keyword">if</span> (response.TryGetResult(<span class="hljs-keyword">out</span> <span class="hljs-keyword">var</span> result))
    {
        Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{name}</span> status: <span class="hljs-subst">{result.Status}</span> (cars: <span class="hljs-subst">{result.NumCars}</span>, trucks: <span class="hljs-subst">{result.NumTrucks}</span>)"</span>);
    }
</code></pre>
<p>This is a good base point for using AI to extract data from images, and there are so many use cases for this feature.</p>
<h2 id="heading-repo">Repo</h2>
<ul>
<li><a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">samples-microsoft-extensions-ai</a></li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">https://www.youtube.com/watc</a><a target="_blank" href="https://www.youtube.com/watch?v=qcp6ufe_XYo">h?v=qcp6ufe_XYo</a></p>
</li>
<li><p><a target="_blank" href="https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/9.0.0-preview.9.24556.5">https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/9.0.0-preview.9.24556.5</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Simple chat app with functions]]></title><description><![CDATA[I created a simple chat app that can talk to OpenAI, and I added to this by adding function calling. Meaning the AI can do more than just browse the internet, you can add some logic to your app.
The aim of Microsoft.Extensions.AI is to make the code ...]]></description><link>https://rachaelkeenan.dev/simple-chat-app-with-functions</link><guid isPermaLink="true">https://rachaelkeenan.dev/simple-chat-app-with-functions</guid><category><![CDATA[Microsoft.Extension.AI]]></category><category><![CDATA[openai]]></category><category><![CDATA[.NET]]></category><category><![CDATA[C#]]></category><category><![CDATA[AI]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Tue, 21 Jan 2025 07:29:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/2EJCSULRwC8/upload/2cd5fdfb78e16dd8acbd574b0c1516d3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I created a simple chat app that can talk to OpenAI, and I added to this by adding function calling. Meaning the AI can do more than just browse the internet, you can add some logic to your app.</p>
<p>The aim of <a target="_blank" href="http://Microsoft.Extensions.AI">Microsoft.Extensions.AI</a> is to make the code more reusable, meaning you can easily swap out the LLMs being used with one line of code rather than multiple.</p>
<pre><code class="lang-csharp">IChatClient innerChatClient = <span class="hljs-keyword">new</span> OpenAIClient(Environment.GetEnvironmentVariable(<span class="hljs-string">"OPENAI_API_KEY"</span>))
    .AsChatClient(<span class="hljs-string">"gpt-4o-mini"</span>);
</code></pre>
<p>I have previously created an AI assistant using OpenAI in a Blazor app <a target="_blank" href="https://github.com/rachkeenan/sample-ai-chatbot-blazor">sample-ai-chatbot-blazor</a>. I wanted to test out the new ways to add LLMs to my app. Although I only created this current app as a console app, I aim to add this in to my current Blazor app which is more user friendly.</p>
<p>I followed the examples in this YouTube video which was featured on .NET Conf event in November 2024, but specifically this video <a target="_blank" href="https://www.youtube.com/watch?v=qcp6ufe_XYo">AI Building Blocks - A new, unified AI layer</a>.</p>
<p>The chat app is simple, add the LLM, hardcode in a message and write out the AI’s response to the console.</p>
<p>Adding the function calling was a bit more complex, in the sense of more code was needed for setup. Function calling needed to be enabled on the <code>IChatClient</code>, I did this through a <code>ChatClientBuilder</code>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> chatClientBuilder = <span class="hljs-keyword">new</span> ChatClientBuilder(innerChatClient).UseFunctionInvocation();

IChatClient client = chatClientBuilder.Build();
</code></pre>
<p>I then added a class for my function, which had a method for “adding socks to a cart” and a method for getting a price. These function are then added to the <code>ChatOptions</code> under <code>Tools</code>, and then the <code>ChatOptions</code> is called with the AI’s response.</p>
<pre><code class="lang-csharp">ChatOptions chatOptions = <span class="hljs-keyword">new</span>()
{
    Tools = [AIFunctionFactory.Create(cart.GetPrice), AIFunctionFactory.Create(cart.AddSocksToCart)]
};

<span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> client.CompleteAsync(messages, chatOptions);
</code></pre>
<p>You also need to add some context to the AI’s prompt for it to understand the function.</p>
<p>For the example I followed in this video, the AI assistant essentially promotes socks and tries to sell socks to the user. The user can ask how much for X pairs or per pair and if the user agrees to buy an amount of socks the AI with simulate adding these socks to a cart and give the user a total price.</p>
<p>Here is an example of the AI assistant calling the function</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737443988955/5c121c68-c7ce-4b84-aa4c-968f926d6b6d.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-repos">Repos</h3>
<ul>
<li><p><a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">samples-microsoft-extensions-ai</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/rachkeenan/sample-ai-chatbot-blazor">sample-ai-chatbot-blazor</a></p>
</li>
</ul>
<h3 id="heading-referenceshttpsgithubcomrachkeenansamples-microsoft-extensions-ai"><a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">References</a></h3>
<ul>
<li><p><a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">https://www.youtube.com/watc</a><a target="_blank" href="https://www.youtube.com/watch?v=qcp6ufe_XYo">h?v=qcp6ufe_XYo</a></p>
</li>
<li><p><a target="_blank" href="https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/9.0.0-preview.9.24556.5">https://www.nuget.org/packages/Microsoft.Extensions.AI.OpenAI/9.0.0-preview.9.24556.5</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Embeddings]]></title><description><![CDATA[Embeddings are a way to represent information, such as text or images, as numbers, also known as a Vector. This represents the concepts within the input, not the characters or pixels, etc.Vectors are an array of numbers that represent something.
Word...]]></description><link>https://rachaelkeenan.dev/embeddings</link><guid isPermaLink="true">https://rachaelkeenan.dev/embeddings</guid><category><![CDATA[#Embeddings]]></category><category><![CDATA[vector embeddings]]></category><category><![CDATA[VectorSearch]]></category><category><![CDATA[C#]]></category><category><![CDATA[.NET]]></category><category><![CDATA[Microsoft]]></category><category><![CDATA[AI]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Thu, 21 Nov 2024 17:24:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/EamEwfBKDNk/upload/ee117e502a09687b48ce8cac1fb6ec72.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Embeddings</strong> are a way to represent information, such as text or images, as numbers, also known as a <strong>Vector</strong>. This represents the concepts within the input, not the characters or pixels, etc.Vectors are an array of numbers that represent something.</p>
<p>Words - for a word it might represent a meaning or relationship</p>
<p>Image - for an image it might represent colours, shapes or patterns</p>
<p>I have mainly used embeddings for <strong>Search</strong> capabilities, searching indexes/text. This is a good use case in the modern world of AI because embeddings measure the relatedness of vectors using their distance. It can be used to match your query to relevant documents. A small distance suggests that the vectors share a high relativity, whereas a large distance would suggest a low relativity.</p>
<p>Words like “cat”, “dog”, “rabbit” will be close together because they’re all animals or like “car”, “truck”, “bus” are all vehicles. Whereas, “truck”, “apple”, “mouse”, would be far apart because they are not related in any way.</p>
<p>Other use cases may be:</p>
<ol>
<li><p>Clustering - grouping text strings by their similarity</p>
</li>
<li><p>Recommendations - items can be suggested based on text strings that are closely related</p>
</li>
<li><p>Classification - assigning text strings to their most related label</p>
</li>
</ol>
<p>The embeddings would look similar to this.</p>
<pre><code class="lang-plaintext"> 0.009120221     -0.011264438    -0.009196174    0.0696432       0.048002396     
 0.0050245933    -0.044683825    0.00040386632   -0.013437866    0.007174652     
 0.023650644     -0.008611919    0.022260118     0.027015954    0.0236857        
 0.014991985     -0.025613742    -0.033325907    -0.014162343    0.041832663     
 0.0064793886    0.03145629      0.01658116      -0.022937853    0.026712142     
 0.028324686     -0.0040342812   0.026782252     0.045478415    -0.012327782
</code></pre>
<p>If querying something from a HR handbook, for example, you should receive the relevant data points to your question. Below is a snippet showing the text using the embeddings and what it would return.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> candidates = <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[] { <span class="hljs-string">"Onboarding process for new employees"</span>, 
<span class="hljs-string">"Understanding Our Company Values"</span>, <span class="hljs-string">"Navigating the Office Layout"</span>, 
<span class="hljs-string">"Accessing Car Park E"</span>, <span class="hljs-string">"Dress Code Guidelines"</span>, <span class="hljs-string">"Using the Company Intranet"</span>, 
<span class="hljs-string">"Employee Benefits Overview"</span>, <span class="hljs-string">"Requesting Time Off"</span>, <span class="hljs-string">"Reporting Workplace Incidents"</span>, 
<span class="hljs-string">"Office Etiquette and Conduct"</span> };
</code></pre>
<pre><code class="lang-plaintext">Query: company values

(0.6882966): Understanding Our Company Values
(0.38679683): Employee Benefits Overview
(0.31320179): Using the Company Intranet
</code></pre>
<p>References</p>
<p>.NET Conf 2024 - Day 1 <a target="_blank" href="https://www.youtube.com/watch?v=hM4ifrqF_lQ&amp;t=7268s">https://www.youtube.com/watch?v=hM4ifrqF_lQ&amp;t=7268s</a></p>
<p>The code samples I reference can be found here: <a target="_blank" href="https://github.com/rachkeenan/samples-microsoft-extensions-ai">https://github.com/rachkeenan/samples-microsoft-extensions-ai</a></p>
]]></content:encoded></item><item><title><![CDATA[Domain Name System (DNS)]]></title><description><![CDATA[I registered a domain for myself for a college class. And I realised this would take a while for it to actually register to all the internet DNS servers, such as Google, etc. This led me to look into where my domain is currently available, I used dns...]]></description><link>https://rachaelkeenan.dev/domain-name-system-dns</link><guid isPermaLink="true">https://rachaelkeenan.dev/domain-name-system-dns</guid><category><![CDATA[dns]]></category><category><![CDATA[ip address]]></category><category><![CDATA[domainnames]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Sat, 02 Mar 2024 18:06:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Q1p7bh3SHj8/upload/2f03d9ecd872b902204638e492e23cde.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I registered a domain for myself for a college class. And I realised this would take a while for it to actually register to all the internet DNS servers, such as Google, etc. This led me to look into where my domain is currently available, I used <a target="_blank" href="http://dnschecker.org">dnschecker.org</a>, but you can also use your terminal (PowerShell) to check this using the command <code>nslookup &lt;domain name&gt;</code>. From this I wanted to look more into what DNS is and how you can change your DNS server.</p>
<h3 id="heading-what-is-a-dns">What is a DNS?</h3>
<p>The Domain Name System (DNS) is essentially a phonebook for the internet, it is a database in which domain names are stored and translated into corresponding IP (Internet Protocol) addresses. For example, if you were to search <a target="_blank" href="http://google.com">google.com</a> (domain name), a server behind the scenes maps that domain name to a designated IP address. Google has many IP addresses linked to its domain, there are various reasons for having multiple IP addresses, such as load balancing, scale of operations and for backup measures.</p>
<p>Most of these IP address are IPv4 addresses, but some larger domains, like Google, may also have IPv6 addresses. The DNS server is the server your computer or browser uses to look up these different domains (IP addresses), they essentially manage the mapping of domain names to their corresponding IP address(es)</p>
<h3 id="heading-how-do-i-check-my-dns">How do I check my DNS?</h3>
<p>A handy way to check your current DNS server is to use your terminal (PowerShell) and the command <code>nslookup</code>, this will show you the server that your computer is currently using. As default, this would usually be your router but could be your internet service provider if there is no DNS set up on your router.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709402419056/8311e465-eb07-4a68-b7ce-8b6e385e635c.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-can-i-change-my-dns">Can I change my DNS?</h3>
<p>If you wanted to change your default DNS, which I previously mentioned is either your router or internet service provider, you can do so in your network settings on your computer.</p>
<ol>
<li><p>Select the Network &amp; Internet settings</p>
</li>
<li><p>Select Advanced Network settings</p>
</li>
<li><p>Click on Wi-Fi to open the dropdown</p>
<ul>
<li><p>Select edit on the More adapter options</p>
</li>
<li><p>You will be given a Wi-Fi Properties window (like below), here select IPv4After clicking IPv4 you will be brought to this window</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709402598536/45bc0004-1539-4553-830f-5c44a29d4b65.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><p>Internet Protocol Version 4 (TCP/IPv4) Properties window will open, here you will see default options selected. Here you will need to select the second option and add in your your preferred and alternate DNS servers, I used Google’s DNS servers. Select ok to confirm your changes</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709402625161/b12855b9-3be0-456e-bc4f-f6664ea32b76.png" alt class="image--center mx-auto" /></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709402640391/c977dd50-f935-46df-ae68-edf26c000540.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>When you use the <code>nslookup</code> command after this change you will instead see the DNS server address for Google rather that your default DNS server address.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1709402431217/fd9448d4-1695-447f-a766-a4d243a91bad.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA['INVEST' Guidelines for Agile User Stories]]></title><description><![CDATA["INVEST" was invented by Bill Wake and is an acronym that spells out how best to write effective and valuable user stories in Agile development. Each word in "INVEST" is a set of criteria that needs to be met to enhance the composition of the user st...]]></description><link>https://rachaelkeenan.dev/invest-guidelines-for-agile-user-stories</link><guid isPermaLink="true">https://rachaelkeenan.dev/invest-guidelines-for-agile-user-stories</guid><category><![CDATA[agile]]></category><category><![CDATA[agile development]]></category><category><![CDATA[SDLC]]></category><category><![CDATA[user stories]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Mon, 22 Jan 2024 12:00:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/jp3Wt6O0v7E/upload/ed72ee44736957cf27f6afcdc287d5e3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>"INVEST" was invented by Bill Wake and is an acronym that spells out how best to write effective and valuable user stories in Agile development. Each word in "INVEST" is a set of criteria that needs to be met to enhance the composition of the user stories.</p>
<p>I wanted to use code examples so that I can illustrate that "INVEST" can be linked to the development of code and developers can benefit from these criteria.</p>
<p>A good user story will incorporate these 6 criteria:</p>
<p><strong>I</strong>ndependent: a user story can be executed without reliance on any other user story, system or team.</p>
<p><em>Example</em>: As a user, I want to be able to log in using my email and password.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Route(<span class="hljs-meta-string">"api/[controller]"</span>)</span>]
[<span class="hljs-meta">ApiController</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AuthController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> List&lt;User&gt; registeredUsers = <span class="hljs-keyword">new</span> List&lt;User&gt;
    {
        <span class="hljs-keyword">new</span> User { Id = <span class="hljs-number">1</span>, Email = <span class="hljs-string">"test1@example.com"</span>, Password = <span class="hljs-string">"password123"</span> },
        <span class="hljs-keyword">new</span> User { Id = <span class="hljs-number">2</span>, Email = <span class="hljs-string">"test2@example.com"</span>, Password = <span class="hljs-string">"Password321"</span> }
    };

    [<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"login"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">Login</span>(<span class="hljs-params">[FromBody] UserLoginRequest loginRequest</span>)</span>
    {
        <span class="hljs-comment">// Check if the entered email and password match any registered user</span>
        <span class="hljs-keyword">var</span> user = registeredUsers.FirstOrDefault(u =&gt; u.Email == loginRequest.Email &amp;&amp; u.Password == loginRequest.Password);

        <span class="hljs-keyword">if</span> (user != <span class="hljs-literal">null</span>)
        {
            <span class="hljs-comment">// Successful</span>
            <span class="hljs-keyword">return</span> Ok(<span class="hljs-keyword">new</span> { Message = <span class="hljs-string">"Login successful!"</span>, UserId = user.Id });
        }
        <span class="hljs-keyword">else</span>
        {
            <span class="hljs-comment">// Not successful</span>
            <span class="hljs-keyword">return</span> Unauthorized(<span class="hljs-keyword">new</span> { Message = <span class="hljs-string">"Invalid email or password. Please try again."</span> });
        }
    }
}
</code></pre>
<p>This user story can be developed independently, it does not have a depency on anything else.</p>
<p><strong>N</strong>egotiable: the user story is open to change, aspects of the story can be removed or adjusted to make the feature quicker to develop. The specific details can be refined at a later stage in development.</p>
<p><em>Example</em>: As a user, I want to be able to filter search results by price.</p>
<p>As developers we need to be able to predict future changes 🔮, and make our code as easy to adjust as the user story.</p>
<pre><code class="lang-csharp"><span class="hljs-function">List&lt;Product&gt; <span class="hljs-title">searchProducts</span>(<span class="hljs-params">SearchProductsRequest request</span>)</span>{
    <span class="hljs-comment">// code goes here</span>
}
<span class="hljs-comment">// called using</span>
<span class="hljs-keyword">var</span> request1 = <span class="hljs-keyword">new</span> SearchProductsRequest() { Category = <span class="hljs-string">"clothes"</span>, MinPrice = <span class="hljs-number">10</span>M };
<span class="hljs-keyword">var</span> request2 = <span class="hljs-keyword">new</span> SearchProductsRequest() { Category = <span class="hljs-string">"clothes"</span>, MinPrice = <span class="hljs-number">10</span>M, MaxPrice = <span class="hljs-number">34</span>M };
<span class="hljs-keyword">var</span> request3 = <span class="hljs-keyword">new</span> SearchProductsRequest() { MinPrice = <span class="hljs-number">10</span>M };

searchProducts(request1);
searchProducts(request2);
searchProducts(request3);

<span class="hljs-comment">// I am using an object because this allows for change within the code,</span>
<span class="hljs-comment">// and can be changed in one place without affecting any other usages of this object.</span>
<span class="hljs-keyword">class</span> <span class="hljs-title">SearchProductsRequest</span> {
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Category { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span> MinPrice { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">decimal</span> MaxPrice { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>This user story can be altered and discussed by the team and stakeholders. The specific requirements (e.g. price range) can be added at a later stage.</p>
<p><strong>V</strong>aluable: it is important that the user story adds value to the end user upon completion.</p>
<p><em>Example</em>: As an online shopper, I want a 'Wishlist' feature, so that I can save items for a later purchase.</p>
<pre><code class="lang-csharp">User user = <span class="hljs-keyword">new</span> User { Id = <span class="hljs-number">1</span>, Username = <span class="hljs-string">"Mary"</span> };

Product laptop = <span class="hljs-keyword">new</span> Product { Id = <span class="hljs-number">101</span>, Name = <span class="hljs-string">"Laptop"</span>, Price = <span class="hljs-number">999.99</span> };
Product headphones = <span class="hljs-keyword">new</span> Product { Id = <span class="hljs-number">102</span>, Name = <span class="hljs-string">"Headphones"</span>, Price = <span class="hljs-number">79.99</span> };
Product phone = <span class="hljs-keyword">new</span> Product { Id = <span class="hljs-number">103</span>, Name = <span class="hljs-string">"Phone"</span>, Price = <span class="hljs-number">499.99</span> };

<span class="hljs-comment">// Add products to the wishlist</span>
Wishlist wishlist = <span class="hljs-keyword">new</span> Wishlist(user);
wishlist.AddToWishlist(laptop);
wishlist.AddToWishlist(headphones);
wishlist.AddToWishlist(phone);

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">User</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Username { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Price { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">WishlistItem</span>
{
    <span class="hljs-keyword">public</span> Product Product { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> DateTime AddedAt { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Wishlist</span>
{
    <span class="hljs-comment">// code goes here</span>
}
</code></pre>
<p>This elavates the users experience when shopping and provides a means to save items for future purchases, thus adding value to the end user.</p>
<p><strong>E</strong>stimable: the team can understand the user story and can determine the effort and resources required to complete the feature.</p>
<p><em>Example</em>: As a user, I want to receive notifications for all new emails recieved.</p>
<p>This story is clear for the team to understand and an estimation of effort can be determined.</p>
<p><strong>S</strong>mall: the user story can be completed in a small timeframe, usually 1-3 days.</p>
<p><em>Example</em>: As a user, I want to see recommendations based on my browsing history.</p>
<pre><code class="lang-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"recommendationsList"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
        <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">var</span> browsingHistory = [
                <span class="hljs-string">'Product A'</span>,
                <span class="hljs-string">'Product B'</span>,
                <span class="hljs-string">'Product C'</span>
            ];

            <span class="hljs-comment">// Get the recommendations list element</span>
            <span class="hljs-keyword">var</span> recommendationsList = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'recommendationsList'</span>);

            <span class="hljs-comment">// Display recommendations based on browsing history</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; browsingHistory.length; i++) {
                <span class="hljs-keyword">var</span> recommendationItem = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'li'</span>);
                recommendationItem.textContent = <span class="hljs-string">'Recommended: '</span> + browsingHistory[i];
                recommendationsList.appendChild(recommendationItem);
            }
        });
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>This user story is simple and concise and could be completed within a single sprint.</p>
<p><strong>T</strong>estable: the user story can be clearly tested when completed to make sure it is in line with the acceptance criteria and works as intened.</p>
<p><em>Example</em>: As a business, I want the 'Submit' button on the form to be disabled until all required fields are filled.</p>
<pre><code class="lang-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"myForm"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"firstName"</span>&gt;</span>First Name:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"firstName"</span> <span class="hljs-attr">required</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"lastName"</span>&gt;</span>Last Name:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"lastName"</span> <span class="hljs-attr">required</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"submitButton"</span> <span class="hljs-attr">disabled</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
        <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-comment">// Get form and submit button</span>
            <span class="hljs-comment">// Add event listeners to form elements</span>
            <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkFields</span>(<span class="hljs-params"></span>) </span>{
                <span class="hljs-comment">// Enable the submit button only if both textboxes are filled</span>
                <span class="hljs-keyword">var</span> firstName = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'firstName'</span>).value;
                <span class="hljs-keyword">var</span> lastName = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'lastName'</span>).value;

                submitButton.disabled = !(firstName !== <span class="hljs-string">''</span> &amp;&amp; lastName !== <span class="hljs-string">''</span>);
            }
        });
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>This user story has clear testing ability through the buttons behaviour, and tests can be automated or manually checked.</p>
<p>Following the 'INVEST' guidelines ensures that the user stories are unambigous, provide value and are attainable. It encourages collaboration between the team and offers a shared understanding of expectations.</p>
]]></content:encoded></item><item><title><![CDATA[EDMx versus Migrations]]></title><description><![CDATA[I first came across EDMx during college when working on a WPF application that required a database. I decided to look back on this assessment I created to see if there was anything I could do differently or add to it to improve it. For my own learnin...]]></description><link>https://rachaelkeenan.dev/edmx-versus-migrations</link><guid isPermaLink="true">https://rachaelkeenan.dev/edmx-versus-migrations</guid><category><![CDATA[edmx]]></category><category><![CDATA[visual studio]]></category><category><![CDATA[entity framework]]></category><category><![CDATA[database migrations]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Sun, 21 Jan 2024 16:24:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/PkbZahEG2Ng/upload/95462b94bc3db1d9164bd666181584d4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I first came across EDMx during college when working on a WPF application that required a database. I decided to look back on this assessment I created to see if there was anything I could do differently or add to it to improve it. For my own learning I decided to start this from scratch which meant recreated the database. I ran into some issues during this recreation of an EDMx database which led me to look into Migrations.</p>
<h2 id="heading-edmx">EDMx</h2>
<p>EDMx is a tool in Visual Studio that allows you to create your database visually with a diagramming tool. This can be helpful when starting out, however this is an outdated method for creating databases as it works with Entity Framework 4.x.</p>
<p>EDMx is a database first approach, this means that you create your database schema first and the models/classes that represent your entities are then created from this schema.</p>
<h2 id="heading-migrations">Migrations</h2>
<p>Migrations can be used in Visual Studio but it can also be used through the CLI and Visual Studio Code. It is a more modern technique to creating databases that are linked to models/classes. It is supported by Entity Framework Core which is the most up-to-date version of Entity Framework.</p>
<p>Migrations work off of a code first approach, this means that you would create your models/classes first and you database is automatically generated or updated based on your code.</p>
<h2 id="heading-edmx-vs-migrations">EDMx vs. Migrations</h2>
<p>As I stated previously I started with using the EDMx method and I came to realise that this technique did not suit my needs. I found that through mistakes I would not be able to update my database if, for example a property type was incorrect, I would have to drop the table and create a new one. I learnt that this would not be viable in the real world because it would mean a loss of data already stored in the database. and also the models first created would not be updated this is another step.</p>
<p>EDMx is suitable for beginners who do not intend to make changes to their database once complete. However if changes are required due to mistakes, whether this is a typo issue or a change to property or even adding/removing a property, be prepared to delete your database and start from scratch.</p>
<p>Migrations, however allows for evolution of your database because it is working from your code. Therefore if you change your code, there is an update for the database but it will not delete the database or its data. There is more version control with Migrations through its migration files. Migrations can also be used in multiple ways, through the CLI, through Visual Studio Code and through the Packet Manager Console in Visual Studio 2022.</p>
<p>My learning from this experience is to look to see if there are better techniques to the same problem, and also to keep up-to-date with evolving technology.</p>
<p>To learn more about Migrations I followed this tutorial: <a target="_blank" href="https://learn.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=visual-studio">https://learn.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=visual-studio</a></p>
]]></content:encoded></item><item><title><![CDATA[Creating a Repository on GitHub through Visual Studio Code]]></title><description><![CDATA[I added my first GitHub repository using the CLI, but this time I tried adding a repository through VS code. This method was surprisingly easy and for newbies like me these are the steps.
Step 1:
Open your code in visual studio code, go to the source...]]></description><link>https://rachaelkeenan.dev/creating-a-repository-on-github-through-visual-studio-code</link><guid isPermaLink="true">https://rachaelkeenan.dev/creating-a-repository-on-github-through-visual-studio-code</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[repository]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Thu, 18 Jan 2024 18:12:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UT8LMo-wlyk/upload/cb5a7c2891d38f97a9b69315696cb482.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I added my first GitHub repository using the CLI, but this time I tried adding a repository through VS code. This method was surprisingly easy and for newbies like me these are the steps.</p>
<p>Step 1:</p>
<p>Open your code in visual studio code, go to the source control.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705599719925/15fb1b2b-3184-4fa7-b026-7159bfd4ef41.png" alt class="image--center mx-auto" /></p>
<p>To create a new repository, if you don't already have one created, select "Initialize Repository". However, if you already have a reposiory on GitHub you can choose the second option "Publish to GitHub".</p>
<p>For this blog I will be focusing on the "Initialize Repository" option.</p>
<p>Step 2:</p>
<p>The next window you will see is the "Commit" window. Here it will show you all the file you have not commited yet, and you can choose a select few or commit all. You should also input a message for your commit.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705600005363/98e11fd1-599c-462a-bf1b-15917f6c905e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705600181509/c59ded53-5dd9-471b-ab4f-2f97ca1d8ae7.png" alt class="image--center mx-auto" /></p>
<p>As I have only one to commit I just continued and was issued this message, I selected yes but if you intend to always commit all your changes select always.</p>
<p>Step 3:</p>
<p>You will be asked to provide access to your GitHub profile for VS code, this will bring you to a window for you to authorize this access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705601221475/6f3b5a96-f427-4064-af9e-108613b77628.png" alt class="image--center mx-auto" /></p>
<p>A pop up for GitHub login will then appear and you must log in for VS code verification.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705601263463/60ca6daa-d47c-468d-9f64-23649c38328e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705601245858/77bfe628-d53e-495d-aa5f-ec7f2a3520b1.png" alt class="image--center mx-auto" /></p>
<p>Step 4:</p>
<p>You will next see a window to "Publish Branch", this pushes your code to GitHub and</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705601411739/1ae321ba-e8a4-49ef-aa1b-ee291f05288f.png" alt class="image--center mx-auto" /></p>
<p>I got a notification to say this was successfully published.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705600691203/fc4d47af-e7e2-4152-bbf1-b26dc10cd2b8.png" alt class="image--center mx-auto" /></p>
<p>This is a more straightforward method, if you don't like using the CLI this is the way to go.</p>
]]></content:encoded></item><item><title><![CDATA[Diagrams as Code]]></title><description><![CDATA[I came across Diagrams as Code during a college assessment where I had to create different UML diagrams based on a given scenario. I tried different diagramming tools, such as Lucid Chart but I just did not like this method, I found it awkward and ve...]]></description><link>https://rachaelkeenan.dev/diagrams-as-code</link><guid isPermaLink="true">https://rachaelkeenan.dev/diagrams-as-code</guid><category><![CDATA[diagramascode]]></category><category><![CDATA[plantuml]]></category><category><![CDATA[MermaidJS]]></category><category><![CDATA[Class Diagrams]]></category><category><![CDATA[Visual Studio Code]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Wed, 17 Jan 2024 20:19:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/lFtttcsx5Vk/upload/7c7185cfb5b3459c126ab2499c0fe4d8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I came across Diagrams as Code during a college assessment where I had to create different UML diagrams based on a given scenario. I tried different diagramming tools, such as Lucid Chart but I just did not like this method, I found it awkward and very time consuming. Then I came across diagrams as code, here I learnt that I could create diagrams using a markdown langauge, as I had already covered different aspects of coding this peaked my interest.</p>
<p>Diagrams as code is a simple way of creating and storing diagram images as plain text. I tried both Mermaid and PlantUML after trialling a standard diagramming tool. I will discuss each and what I liked or did not like.</p>
<p>Both tools can be installed through an extension on Visual Studio Code, if you are using this or through an online editor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705423130089/39a72433-ba7e-4d1e-b4c0-6265cb8ab97c.png" alt="Screenshot of extensions on Visual Studio Code" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705523985078/6f6931b2-4bb4-44d1-af7b-ed5183b0f799.png" alt="Screenshot of PlantUML extension in Visual Studio Code" class="image--center mx-auto" /></p>
<p>If you use the note taking app Notion, Mermaid is an option in the code block, where it also renders the image for you.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705521695757/821f308d-649f-4b16-91d2-57121bf88d87.png" alt="Screenshot of Mermaid editor on Notion app" class="image--center mx-auto" /></p>
<p>Mermaid benefits from its visually appealing documentation, see <a target="_blank" href="https://mermaid.js.org/intro/">https://mermaid.js.org/intro/</a>. However for me it did not work for certain diagrams I had to create for my assignment. I was expected to create a use-case diagram, among others but there was no documentation for creating use-case diagrams with Mermaid. I attempted different ways to create a use case diagram with Mermaid syntax, however it just did not suit what I wanted.</p>
<p>Mermaid does create many diagram types so it is beneficial for that and I cannot fault the tool, it just did not fit my needs at the time so I decided to switch to the PlantUML syntax. The documentation was also very clear with plenty of examples.</p>
<p>One thing to note when if installing PlantUML in Visual Studio Code is that because PlantUML is run from an online server you must in the settings either link it to your own server or link the PlantUML server provided in the extension's information, this was not a default in the settings.</p>
<p>Unlike Mermaid, PlantUML does not have visually appealing documentation. However, all of the information you need is there, see <a target="_blank" href="https://plantuml.com/">https://plantuml.com/</a>. PlantUML had documentation for each diagram I had to create and more. There was a page for each diagram type and this was helpful, it also had lots of examples. I also learnt a few ne things about the diagrams I was creating.</p>
<p>The syntax for both diagramming tools are very similar, but they do have some simple differences. For example, PlantUML is started with "@startUML" and ended with "@endUML", whereas in Visual Studio Code Mermaid is started with "```mermaid". Otherwise, as you can see from both examples the syntax is the same for the class diagrams.</p>
<h3 id="heading-mermaid">Mermaid</h3>
<pre><code class="lang-plaintext">```mermaid

classDiagram

class BookStore{
    # AddToBasket()
}

class Account{
    # Name
    # Address
    # Phone
    # Email
    - Register()
    - Login()
}

class Book{
    # Name
    # Id
    # Description 
    # Price
}

class Basket{
    # BookId
    # BookName
    # Quantity
    # Price
    - Total()
    - Add()
    - Remove()
}

class Checkout{
    # Items
    # Quantity
    # TotalPrice
    - Details()
    - Payment()
    - Verification()
}

BookStore "1" *-- "0..*  " Account
BookStore *-- "0..*" Basket
BookStore *-- "1..*" Book
Basket "1" *-- "1 " Checkout
Book "1" o-- "0..*  " Basket
Account "1 "--&gt;"1" Basket
Account o-- Checkout
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705426366808/171257c3-33e8-4068-9716-1ae32fb3b058.png" alt="Screenshot of Mermaid class diagram" class="image--center mx-auto" /></p>
<h3 id="heading-plantuml">PlantUML</h3>
<pre><code class="lang-plaintext">@startuml classDiagram

abstract class BookStore{
    # AddToBasket()
}
class Account{
    # Name
    # Address
    # Phone
    # Email
    - Register()
    - Login()
}
class Book{
    # Name
    # Id
    # Description 
    # Price
}
class Basket{
    # BookId
    # BookName
    # Quantity
    # Price
    - Total()
    - Add()
    - Remove()
}
class Checkout{
    # Items
    # Quantity
    # TotalPrice
    - Details()
    - Payment()
    - Verification()
}

BookStore "1" *-- "0..*  " Account
BookStore *-- "0..*" Basket
BookStore *-- "1..*" Book
Basket "1" *-- "1 " Checkout
Book "1" o-- "0..*  " Basket
Account "1 "--&gt;"1" Basket
Account o-- Checkout

@enduml
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705425019480/8b6186eb-6ee8-400a-adc9-cc71d692448a.png" alt="Screenshot of PlantUML class diagram" class="image--center mx-auto" /></p>
<p>Diagrams as Code is beneficial because it is stored as plain text it provides more flexibility. It can also be very versatile for developers to read the code and understand the diagrams. It provides a feature of reusability and consistency for teams, and version control because it is stored and changed/updated in one place.</p>
]]></content:encoded></item><item><title><![CDATA[Adding my first repository to GitHub using Git]]></title><description><![CDATA[I am new to using Git and GitHub, but I wanted to add my first project (repository) to my GitHub account using Git commands (CLI). So if you’re a newbie like me hopefully these steps will help.
Steps I used to create a repo:

Create a new repository
...]]></description><link>https://rachaelkeenan.dev/adding-my-first-repository-to-github-using-git</link><guid isPermaLink="true">https://rachaelkeenan.dev/adding-my-first-repository-to-github-using-git</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[repository]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Mon, 20 Nov 2023 16:21:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UT8LMo-wlyk/upload/3dcac027a0f3cad4c6b8a933d829ceed.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I am new to using Git and GitHub, but I wanted to add my first project (repository) to my GitHub account using Git commands (CLI). So if you’re a newbie like me hopefully these steps will help.</p>
<h3 id="heading-steps-i-used-to-create-a-repo">Steps I used to create a repo:</h3>
<ol>
<li><p>Create a new repository</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700510204799/10af39df-6ef8-4929-8133-031dc4052ffe.png" alt class="image--center mx-auto" /></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700510413869/2648f3a2-80c8-4b7c-8fc1-814729766abc.png" alt class="image--center mx-auto" /></p>
<p> a. Name your repository</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700510451078/9563b261-be7f-4271-b961-1b6174e1249d.png" alt class="image--center mx-auto" /></p>
<p> b. Add a <a target="_blank" href="http://README.md">README.md</a> file, here you can give a more in-depth description of your work.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700510480873/2a52a2b7-36c4-47fb-a1a8-b6696b98699e.png" alt class="image--center mx-auto" /></p>
<p> c. Add a .gitignore file, a drop-down list of tools is provided during the initial setup. This will not allow specified files to be uploaded to the repository.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700510515753/8c41c938-ce60-4bb6-8901-9d74c8f56717.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Using the Git CLI, <code>clone</code> the repository to the computer to a selected folder, for example, <code>C:\Users\&lt;userprofile&gt;</code></p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">clone</span> &lt;https://github.com/&gt;&lt;userprofile&gt;/&lt;reponame&gt;.git
</code></pre>
<ul>
<li><p>this will clone the repository into the folder you have chosen and create a folder with the repository name</p>
<ul>
<li>this will create a folder with all the repository files you have clones</li>
</ul>
</li>
</ul>
</li>
<li><p>For my example I had a previous project I wanted to add so I copied and pasted the files into the repository folder</p>
</li>
<li><p>I then did a <code>status</code> request, this showed me that my branch was up to date and that there were files not tracked within the folder</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> &lt;reponame&gt;
 git status

 <span class="hljs-comment"># Output</span>
 On branch main
 Your branch is up to date with <span class="hljs-string">'origin/main'</span>.

 Untracked files:
   (use <span class="hljs-string">"git add &lt;file&gt;..."</span> to include <span class="hljs-keyword">in</span> what will be committed)
         example.sln
         src/

 nothing added to commit but untracked files present (use <span class="hljs-string">"git add"</span> to track)
</code></pre>
</li>
<li><p>These files now need to be added to the repository in order to be committed.</p>
<ol>
<li>these files can be added individually by name or by using <code>add .</code></li>
</ol>
</li>
</ol>
<pre><code class="lang-bash">    git add .

    git add src
</code></pre>
<ol>
<li><p>Now I can commit these changes by using the commit command, with this I need to add a <code>commit</code> comment using <code>-m</code>, see the example below:</p>
<pre><code class="lang-bash"> git commit -m <span class="hljs-string">"Added code files"</span>
</code></pre>
</li>
<li><p>This has committed the files to the repository, they must now be pushed to the online repository (Github)</p>
<pre><code class="lang-bash"> git push
</code></pre>
</li>
<li><p>When using the <code>push</code> command you may be asked to sign into your GitHub profile.</p>
<ol>
<li><p>this can be done through the Git login window</p>
</li>
<li><p>or you can log in using the CLI</p>
</li>
</ol>
</li>
<li><p>GitHub login</p>
<ol>
<li><p>you will be asked for a username first and then a password</p>
</li>
<li><p>I ran into issues using my GitHub password, it did not want to accept this. Instead, it wants you to use a token password (this worked better in the CLI)</p>
<ol>
<li><p>You can find access to tokens under your profile settings</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700496920760/bdbf48ed-6678-4440-80b9-538375ef2e84.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>you will then find a list on the left-hand side of your screen, this will give you a &lt;&gt; Developer settings option</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700496931685/0f48d22a-1798-48bc-a91a-034b747daf11.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>I then selected Personal access tokens and it gave me 2 options, I used Tokens (classic) and followed the steps to setting up the token.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700496950382/e979c22c-0f3b-40b0-89a3-0cc09bf792d7.png" alt class="image--center mx-auto" /></p>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Fine-grained tokens are more secure and can choose to allow access to selected repos. I chose Tokens (classic) because I am new to tokens and it seemed like a more straightforward token option for a beginner as it allows access to all repos. But, I can understand why someone would want to use Fine-grained tokens to secure their work.</div>
 </div></li>
</ol>
</li>
</ol>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Hexadecimal Conversions]]></title><description><![CDATA[Hexadecimal is a base 16 number system, it is made up of numbers 0-9 and letters A-F. In this blog post, I will look at converting Hexadecimal to Decimal and Binary numbers.
Hexadecimal to Decimal
Converting a hexadecimal number to a decimal number i...]]></description><link>https://rachaelkeenan.dev/hexadecimal-conversions</link><guid isPermaLink="true">https://rachaelkeenan.dev/hexadecimal-conversions</guid><category><![CDATA[number system]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[hexadecimal]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Mon, 16 Oct 2023 11:00:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3k9PGKWt7ik/upload/26110ae8758398c207699b209064a9fa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hexadecimal is a base 16 number system, it is made up of numbers 0-9 and letters A-F. In this blog post, I will look at converting Hexadecimal to Decimal and Binary numbers.</p>
<h3 id="heading-hexadecimal-to-decimal">Hexadecimal to Decimal</h3>
<p>Converting a hexadecimal number to a decimal number is similar to converting binary to decimal, but in this case, we use powers of 16 because hexadecimal is a base-16 system. Here are the steps involved:</p>
<ol>
<li><p><strong>Identify the Hexadecimal Digits:</strong> Begin by identifying each digit in the hexadecimal number. Hexadecimal uses digits from 0 to 9 and letters from A to F, representing values 10 to 15 in decimal.</p>
</li>
<li><p><strong>Convert Hexadecimal Letters to Decimal:</strong> If you encounter any letters (A, B, C, D, E, or F) in the hexadecimal number, replace them with their decimal equivalents: A is 10, B is 11, C is 12, D is 13, E is 14, and F is 15.</p>
</li>
<li><p><strong>Calculate Decimal Value for Each Digit:</strong> Starting from the rightmost digit and moving to the left, assign an appropriate power of 16 to each digit. The rightmost digit has a power of 0, the next one has a power of 1, the next one has a power of 2, and so on. Multiply each digit by 16 raised to its respective power and sum up these values.</p>
</li>
<li><p><strong>Add Up the Values:</strong> Sum up the decimal values obtained for each digit to get the final decimal equivalent.</p>
</li>
</ol>
<h5 id="heading-examples"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701888938/270ee863-c3f4-41fc-81aa-fb2cbc54b562.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701898979/11251fe3-f89d-4235-99b3-51a75edaf169.png" alt /></p>
<h4 id="heading-fractional-hexadecimal-to-decimal"><strong>Fractional Hexadecimal to Decimal</strong></h4>
<p>To convert this number to a decimal you use 16 to the power of a minus, meaning anything before the decimal point is positive (2^3) and anything after the decimal point is negative (16^-1)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701919849/fcf6a6a6-ef73-4f82-a8f9-5c44a831b31d.png" alt /></p>
<h3 id="heading-hexadecimal-to-binary">Hexadecimal to Binary</h3>
<ol>
<li><p><strong>Convert the Hexadecimal value into its equivalent decimal value:</strong> In this step, you correctly mention that you need to convert each hexadecimal digit into its decimal equivalent. For example, A would be 10, and D would be 13.</p>
</li>
<li><p><strong>Convert each individual digit from the hexadecimal number into a 4-digit binary number:</strong> This step is where the clarification is needed. Instead of converting each individual digit into a 4-digit binary number, you should convert each hexadecimal digit into its 4-bit binary representation. Hexadecimal digits can represent values from 0 to 15, which require 4 bits to represent. Here's how you can do it:</p>
</li>
</ol>
<ul>
<li><p>0 in hexadecimal is 0000 in binary.</p>
</li>
<li><p>1 in hexadecimal is 0001 in binary.</p>
</li>
<li><p>2 in hexadecimal is 0010 in binary.</p>
</li>
<li><p>...</p>
</li>
<li><p>9 in hexadecimal is 1001 in binary.</p>
</li>
<li><p>A in hexadecimal is 1010 in binary.</p>
</li>
<li><p>B in hexadecimal is 1011 in binary.</p>
</li>
<li><p>...</p>
</li>
<li><p>F in hexadecimal is 1111 in binary.</p>
</li>
</ul>
<ol>
<li><strong>Write these binary numbers from start to finish:</strong> After converting each hexadecimal digit into its 4-bit binary representation, you should write these binary digits from start to finish. For example, if your hexadecimal number is A9, you would convert 'A' to '1010' and '9' to '1001', and then write them together as '10101001'. So, your first binary digits should match 'A', and the second set should match '9'.</li>
</ol>
<h5 id="heading-examples-1"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702042462/fbcd3405-00f1-4525-b125-fa249908d150.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702051858/58e6f8f6-3b4a-4ae0-a069-eed171cff442.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702072814/a65b643c-be90-4f05-8cbf-c69b1644e9ae.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Decimal Conversions]]></title><description><![CDATA[Decimal is a base 10 number system, made up of digits 0-9. In this blog post, I will look at converting Decimal to Hexadecimal and Binary numbers.
Decimal to Binary
Helps to know the powers of 2

Converting a decimal number to binary involves repeate...]]></description><link>https://rachaelkeenan.dev/decimal-conversions</link><guid isPermaLink="true">https://rachaelkeenan.dev/decimal-conversions</guid><category><![CDATA[number system]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[decimal]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Fri, 13 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GQ327RPuxhI/upload/d4faea78463b8d8ffd3a7e432949e2e7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Decimal is a base 10 number system, made up of digits 0-9. In this blog post, I will look at converting Decimal to Hexadecimal and Binary numbers.</p>
<h3 id="heading-decimal-to-binary">Decimal to Binary</h3>
<p>Helps to know the powers of 2</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701465191/4553e9d1-2c95-4ddb-90a2-775441f6c4a5.png" alt /></p>
<p>Converting a decimal number to binary involves repeatedly dividing the decimal number by powers of 2 while noting the remainder. You start with the largest power of 2 less than or equal to the decimal number and write '1' if it goes into the number or '0' if it doesn't. Then, subtract the result from the decimal number and continue with the remainder, repeating the process until there's no remainder left. The binary representation is the sequence of '1s' and '0s' you've written down.</p>
<p>There are two methods to convert a decimal number to a binary number</p>
<ol>
<li><p>Subtraction method</p>
</li>
<li><p>Successive division</p>
</li>
</ol>
<h4 id="heading-subtraction-method"><strong>Subtraction method</strong></h4>
<p>Using the powers of 2 system, choose the highest number that will go into your decimal number.</p>
<h5 id="heading-examples"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701541399/cbbb66fe-afd9-4a66-a8f6-ed7e22f9de81.png" alt /></p>
<ol>
<li><p>Start with the largest power of 2 that is less than or equal to 75, which is 64. Since 64 goes into 75, we can use it, and we write down a '1' as the first binary digit.</p>
</li>
<li><p>Now, subtract 64 from 75, which leaves us with a remainder of 11.</p>
</li>
<li><p>Next, find the largest power of 2 less than or equal to the remainder, which is 8. Since 8 goes into 11, we write down another '1' as the second binary digit.</p>
</li>
<li><p>Subtract 8 from the remainder (11 - 8 = 3).</p>
</li>
<li><p>Continue this process, finding the largest power of 2 for the remaining remainder. The next power of 2 is 2, and since 2 goes into 3, we write down '1' as the third binary digit.</p>
</li>
<li><p>Subtract 2 from the remainder (3 - 2 = 1).</p>
</li>
<li><p>Finally, for the remaining remainder (1), the largest power of 2 less than or equal to it is 1 itself. Since 1 goes into 1, we write down '1' as the fourth binary digit.</p>
</li>
<li><p>There are no more remainders left, so we stop.</p>
</li>
</ol>
<p>So, the binary representation of the decimal number 75 is 100101.</p>
<p>Here are two more examples:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701564240/0315962a-d783-4844-b99a-bd8485fd3ad7.png" alt /></p>
<p>This next example required a larger power of 2 base, the next number to add is 256 (128 x 2)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701584930/3aba31f3-ccbb-469a-95c1-6a619d7708d1.png" alt /></p>
<h4 id="heading-successive-division"><strong>Successive division</strong></h4>
<p>The successive division method for converting a decimal number to binary involves repeatedly dividing the decimal number by 2 until you reach 0.</p>
<ol>
<li><p>Start by dividing the decimal number by 2.</p>
</li>
<li><p>If there is no remainder, write down a '0' as the binary digit.</p>
</li>
<li><p>If there is a remainder, write down '1' as the binary digit.</p>
</li>
<li><p>Continue this process, using the result of each division as the input for the next division.</p>
</li>
<li><p>Repeat steps 2 and 3 until you've divided all the way to 0.</p>
</li>
</ol>
<p>For example, if you have the decimal number 75:</p>
<ul>
<li><p>First division: 75 ÷ 2 = 37 with a remainder of 1, so you write down '1'.</p>
</li>
<li><p>Second division: 37 ÷ 2 = 18 with a remainder, so you write down '1'.</p>
</li>
<li><p>Third division: 18 ÷ 2 = 9 with no remainder, so you write down “0”</p>
</li>
<li><p>Fourth division: 9 ÷ 2 = 4 with a remainder of 1, so you write down '1'.</p>
</li>
<li><p>Fifth division: 4 ÷ 2 = 2 with no remainder, so you write down '0'.</p>
</li>
<li><p>Sixth division: 2 ÷ 2 = 1 with no remainder, so you write down '0'.</p>
</li>
<li><p>Seventh division: 1 ÷ 2 = 0 with a remainder of 1, so you write down '1'.</p>
</li>
</ul>
<p>This method is read from the bottom up, meaning the final division calculated is the first digit of the binary number.</p>
<ul>
<li>The binary number for the above example of 75 is 1001011</li>
</ul>
<p>MSB = Most Significant Bit</p>
<p>LSB = Least Significant Bit</p>
<h5 id="heading-examples-1"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701609596/e53604d3-ee98-426c-8108-a41c7a140933.png" alt /></p>
<h3 id="heading-decimal-with-a-decimal-point-to-a-binary">Decimal with a decimal point to a Binary</h3>
<ol>
<li><p>Divide the full number by 2, your remainder numbers make up your binary number before the decimal point.</p>
</li>
<li><p>Multiply anything after the decimal point by 2 - once the numbers after the decimal point reach 0, the numbers before your decimal point make up the binary number after the decimal point</p>
</li>
</ol>
<h5 id="heading-examples-2"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701664113/6cba7db0-8692-43ba-ad0f-e1fca2312fe5.png" alt /></p>
<h3 id="heading-decimal-to-hexadecimal">Decimal to Hexadecimal</h3>
<p>Decimal = base 10 system</p>
<ul>
<li>0-9</li>
</ul>
<p>Hexadecimal = base 16 system</p>
<ul>
<li>0-9, A-F</li>
</ul>
<p>To convert a decimal number to a hexadecimal number, you can follow these steps:</p>
<ol>
<li><p><strong>Divide the Decimal Number by 16:</strong> Begin by dividing the decimal number by 16.</p>
</li>
<li><p><strong>Keep Track of Remainders:</strong> As you perform the division, keep track of the remainders at each step. The remainder will be a digit in the hexadecimal representation.</p>
</li>
<li><p><strong>Continue Division:</strong> Continue the division process, using the quotient obtained from the previous step as the new dividend, until the quotient becomes zero.</p>
<ol>
<li>a <strong>quotient</strong> is a quantity produced by the division of two numbers.</li>
</ol>
</li>
<li><p><strong>Convert Remainders to Hexadecimal Digits:</strong> At each step where you calculate a remainder, you will have a number between 0 and 15. These numbers need to be converted to their hexadecimal equivalents:</p>
<ol>
<li><p>0 to 9 remain the same in hexadecimal.</p>
</li>
<li><p>10 to 15 is equivalent to 'A-F' in hexadecimal.</p>
</li>
</ol>
</li>
<li><p><strong>Arrange Hexadecimal Digits:</strong> Write down the hexadecimal digits obtained from the remainders in reverse order, starting from the last remainder you calculated.</p>
</li>
</ol>
<h5 id="heading-examples-using-a-calculator"><strong>Examples: using a calculator</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701699176/48cc69df-2fd5-4b80-b5a6-dcc60e8175d8.png" alt /></p>
<p>The numbers are read from bottom to top, therefore the hexadecimal for 479 is 1DF.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701723569/e0434fd2-1c39-41c7-aa07-6b2dad8628ee.png" alt /></p>
<p>The hexadecimal for 894 is 37E</p>
<h5 id="heading-examples-using-long-division-no-calculator"><strong>Examples: Using long division (no calculator)</strong></h5>
<p>It is helpful to know the multiples of 16 for this method</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701806433/5aa97a76-ab45-4473-ab78-d32013ec3862.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701841366/7e199167-46de-4e03-ac56-35099a5528fe.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701852288/aec614a1-622b-4d37-8b81-8dfc54148d98.jpeg" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Binary Conversions]]></title><description><![CDATA[Binary is a base 2 number system and is made up of 0s and 1s. In this blog post, I will look at converting Binary to Decimal and Hexadecimal numbers. I will also look at converting Binary fractions into Decimals, and Binary addition and subtraction. ...]]></description><link>https://rachaelkeenan.dev/binary-conversions</link><guid isPermaLink="true">https://rachaelkeenan.dev/binary-conversions</guid><category><![CDATA[number system]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[binary]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Tue, 10 Oct 2023 16:30:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KgLtFCgfC28/upload/6292668b664d77362f1c14768c6e4daf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Binary is a base 2 number system and is made up of 0s and 1s. In this blog post, I will look at converting Binary to Decimal and Hexadecimal numbers. I will also look at converting Binary fractions into Decimals, and Binary addition and subtraction. Lastly, I will cover 2's Complement.</p>
<h3 id="heading-binary-to-decimal">Binary to Decimal</h3>
<p>Here is a handy table to help with calculations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701263604/08c8cb96-b9fc-4803-a675-b6302124f462.png" alt /></p>
<p>When converting a binary number to a decimal number, you use powers of 2 because binary is a base-2 number system. In a base-2 system, each digit (bit) can have one of two values: 0 or 1. By using powers of 2, you can represent any decimal number by combining these binary digits.</p>
<p>Here's how it works:</p>
<ol>
<li><p>The rightmost digit in a binary number represents 2^0 (2 raised to the power of 0), which is equal to 1. So, if you have a 1 in the rightmost position, it contributes 1 to the decimal value. If it's 0, it contributes 0 to the decimal value.</p>
</li>
<li><p>The next digit to the left represents 2^1 (2 raised to the power of 1), which is equal to 2. So, if you have a 1 in this position, it contributes 2 to the decimal value. If it's 0, it contributes 0.</p>
</li>
<li><p>The next digit to the left represents 2^2 (2 raised to the power of 2), which is equal to 4. So, if you have a 1 in this position, it contributes 4 to the decimal value. If it's 0, it contributes 0.</p>
</li>
</ol>
<p>This pattern continues for each position to the left. Each position represents a power of 2 that is one greater than the position to its right. Therefore, you add up the values contributed by each position based on whether it's a 1 or a 0 to get the decimal equivalent of the binary number.</p>
<h5 id="heading-examples"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701323549/1d13f75f-8d85-46de-a70e-664164a39f6c.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-binary-fractions">Binary Fractions</h3>
<p>An example of a binary fraction is 1100.101</p>
<p>To convert this number to a decimal you use 2 to the power of a minus, meaning anything before the decimal point is positive (2^3) and anything after the decimal point is negative (2^-1)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701390381/0f60a2c7-cd01-4576-bd20-68c9c3a8847a.png" alt /></p>
<p>Similar to the table used for the positive powers, here is a table for the negative</p>
<h5 id="heading-examples-1"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701421520/a6ad8bfa-e6c4-4e7d-937e-f49ba54a6c09.png" alt /></p>
<h3 id="heading-binary-to-hexadecimal">Binary to Hexadecimal</h3>
<ol>
<li><p><strong>Group into Sets of Four</strong>: Begin by separating the binary number into sets of four digits, starting from the right. If the leftmost group has fewer than four digits, add leading zeros to make it a complete group of four (e.g., 1101 becomes 0011 0101). This step ensures that each group corresponds to a single hexadecimal digit.</p>
</li>
<li><p><strong>Convert Each Group to Decimal</strong>: Now, convert each group of four binary digits into its decimal equivalent. You can do this by multiplying each digit by 2 raised to the power of its position from right to left (starting with 0 for the rightmost digit) and then summing up these values. For example, to convert 1101 to decimal:</p>
<ol>
<li>1 * <em>2^3 + 1</em> * 2^2 + 0 <em>\</em> 2^1 + 1<em> \</em> 2^0 = 8 + 4 + 0 + 1 = 13</li>
</ol>
</li>
</ol>
<p>    So, the first group, 1101, is equivalent to the decimal value 13.</p>
<ol>
<li><strong>Convert Decimal Values to Hexadecimal</strong>: Finally, convert the decimal values obtained in step 2 into their hexadecimal equivalents. In hexadecimal, digits range from 0 to 9 and then from A to F. So, for the decimal value 13, its hexadecimal equivalent is D.</li>
</ol>
<p>Repeat steps 2 and 3 for each group of four binary digits, and then combine the hexadecimal equivalents to get the final hexadecimal representation of the binary number.</p>
<p>For example, let's convert the binary number 11010101 to hexadecimal:</p>
<ol>
<li><p>Group into sets of four: 1101 0101</p>
</li>
<li><p>Convert each group to decimal:</p>
<ol>
<li><p>1101 (in binary) = 13 (in decimal)</p>
</li>
<li><p>0101 (in binary) = 5 (in decimal)</p>
</li>
</ol>
</li>
<li><p>Convert decimal values to hexadecimal:</p>
<ol>
<li><p>13 (in decimal) = D (in hexadecimal)</p>
</li>
<li><p>5 (in decimal) = 5 (in hexadecimal)</p>
</li>
</ol>
</li>
</ol>
<p>Combine the results: 11010101 (binary) = D5 (hexadecimal)</p>
<p>So, 11010101 in binary is equivalent to D5 in hexadecimal.</p>
<h5 id="heading-examples-2"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696701992305/88a5ea4f-981f-4bdb-ba6f-9897ab6ee2de.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702002104/586ad4c6-d18b-4e23-8986-97649eb5dc22.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702012088/bafe8988-4f19-43d9-b6aa-f0fb6f7d02f6.png" alt /></p>
<h3 id="heading-binary-addition">Binary Addition</h3>
<p>Adding Binary numbers can be quite simple once you have a bit of practice. It is slightly different to simple addition of a decimal number. There are some things to note.</p>
<ul>
<li><p>0 + 0 = 0</p>
</li>
<li><p>1 + 0 = 1</p>
</li>
<li><p>1 + 1 = 10</p>
<ul>
<li><p>Normal addition would mean 1 + 1 = 2, however when adding Binary numbers this means it has a decimal equivalent of 2.</p>
</li>
<li><p>You must carry over the 1, leaving the first number as 0</p>
</li>
</ul>
</li>
<li><p>1 + 1 + 1 = 11</p>
<ul>
<li><p>Similar to the example above, this example is calculated in two parts:</p>
<ul>
<li>1 + 1 = 0 and you carry over a 1, but in this case, still have an original 1 and now a 0, so 1 + 0 is then calculated giving you a 1.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>In most cases you will have a longer binary number, add these numbers column by column (see Ex. 1).</p>
<p>If you want to check your answers are correct, this can be done by converting the numbers to decimal and adding these.</p>
<h5 id="heading-examples-3"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702128615/edc4fe0e-d26f-4997-aaf6-b694e78452c7.png" alt /></p>
<h3 id="heading-binary-subtraction">Binary Subtraction</h3>
<p>Similar to adding binary numbers, subtraction is again simple once you understand a few things</p>
<ul>
<li><p>1 - 0 = 1</p>
</li>
<li><p>1 - 1 = 0</p>
</li>
<li><p>0 - 1 = ?</p>
<ul>
<li>This equation is usually paired with a longer binary number such as the example below:</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702147798/03c3c959-2a24-40f4-8557-858f567e77e4.png" alt /></p>
<ul>
<li>A number ahead is cancelled where possible to add to the 0 value, so when a is cancelled, a 2 is carried over. Then the equation would read 2 - 1 = 1 or in some cases if the 2 is cancelled and carried over again 1 - 1 = 0</li>
</ul>
<h5 id="heading-examples-4"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702161184/ed18543e-cb82-49b8-b304-34629946ba39.png" alt /></p>
<h3 id="heading-2s-complement">2's Complement</h3>
<p>2's complement is a method used for representing negative numbers in binary and performing binary subtraction. Here are the steps:</p>
<ol>
<li><p>Start with the positive binary representation of the number you want to subtract from.</p>
</li>
<li><p>To find the 2's complement of the number you want to subtract (the negative number), invert all the bits (change 1s to 0s and 0s to 1s).</p>
</li>
<li><p>Add 1 to the result of the inversion.</p>
</li>
<li><p>Now, add the positive binary number and the 2's complement of the negative number using normal binary addition.</p>
</li>
<li><p>If there is a carry-out from the most significant bit (leftmost bit), it indicates overflow, and you can ignore it for most arithmetic operations or handle it as needed.</p>
</li>
</ol>
<h5 id="heading-examples-5"><strong>Examples:</strong></h5>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702210257/1516bce3-0fcb-49b6-b03b-76ffd563b937.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702217951/aba91587-3a63-470b-aead-33ad393f88ad.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696702227064/a56b0a2a-c53d-4e9b-941f-712f67e92234.jpeg" alt /></p>
<p>This process allows you to perform binary subtraction by effectively adding the negative number's 2's complement to the positive number. It simplifies the hardware required for subtraction in computer systems and ensures consistent arithmetic operations for both positive and negative numbers.</p>
]]></content:encoded></item><item><title><![CDATA[Common Number Systems]]></title><description><![CDATA[There are a few different types of number systems, the number systems I will be looking at are Binary, Decimal and Hexadecimal.
Binary
Binary is a numbering system read by computers, it is made up of 0s and 1s. This is a base 2 number system.
A logic...]]></description><link>https://rachaelkeenan.dev/common-number-systems</link><guid isPermaLink="true">https://rachaelkeenan.dev/common-number-systems</guid><category><![CDATA[number system]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Sat, 07 Oct 2023 19:03:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5u6bz2tYhX8/upload/c264f4a916657a3765edaa8568e53334.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are a few different types of number systems, the number systems I will be looking at are Binary, Decimal and Hexadecimal.</p>
<h2 id="heading-binary">Binary</h2>
<p>Binary is a numbering system read by computers, it is made up of 0s and 1s. This is a base 2 number system.</p>
<p>A logic state of 0 means there is an open transistor switch. This means the off/false/no.</p>
<p>A logic state of 1 means there is a closed transistor switch. This means on/true/yes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696703211168/86467a91-d57e-4efa-9d7f-7f0b49ab8d98.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-decimal">Decimal</h2>
<p>Decimal is the most common number system used by humans, but it cannot be read by computers. This is a base 10 number system, it covers digits 0-9.</p>
<h2 id="heading-hexadecimal">Hexadecimal</h2>
<p>Hexadecimal is a number system made up of both numbers and letters. This is a base 16 number system, it covers digits 0-9 and A-F.</p>
<p>Here is a table that shows each number system and compares its equivalents:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Binary</td><td>Decimal</td><td>Hexadecimal</td></tr>
</thead>
<tbody>
<tr>
<td>0000</td><td>0</td><td>0</td></tr>
<tr>
<td>0001</td><td>1</td><td>1</td></tr>
<tr>
<td>0010</td><td>2</td><td>2</td></tr>
<tr>
<td>0011</td><td>3</td><td>3</td></tr>
<tr>
<td>0100</td><td>4</td><td>4</td></tr>
<tr>
<td>0101</td><td>5</td><td>5</td></tr>
<tr>
<td>0110</td><td>6</td><td>6</td></tr>
<tr>
<td>0111</td><td>7</td><td>7</td></tr>
<tr>
<td>1000</td><td>8</td><td>8</td></tr>
<tr>
<td>1001</td><td>9</td><td>9</td></tr>
<tr>
<td>1010</td><td>10</td><td>A</td></tr>
<tr>
<td>1011</td><td>11</td><td>B</td></tr>
<tr>
<td>1100</td><td>12</td><td>C</td></tr>
<tr>
<td>1101</td><td>13</td><td>D</td></tr>
<tr>
<td>1110</td><td>14</td><td>E</td></tr>
<tr>
<td>1111</td><td>15</td><td>F</td></tr>
</tbody>
</table>
</div><p>Each of these number systems can be converted to each other, such as Binary to Decimal and vice versa. In future blog posts, I will cover these conversions.</p>
<p><a target="_blank" href="https://rachael.hashnode.dev/binary-conversions">Binary Conversions</a></p>
<p><a target="_blank" href="https://rachael.hashnode.dev/decimal-conversions">Decimal Conversions</a></p>
<p><a target="_blank" href="https://rachael.hashnode.dev/hexadecimal-conversions">Hexadecimal Conversions</a></p>
]]></content:encoded></item><item><title><![CDATA[How the Software Development Life Cycle helped me]]></title><description><![CDATA[While searching for better ways to plan a web project I found the the Software Development Lifecycle. This is a process that consists of several stages for building and running software applications. It is like a checklist of sorts, there are 6 stage...]]></description><link>https://rachaelkeenan.dev/how-the-software-development-life-cycle-helped-me</link><guid isPermaLink="true">https://rachaelkeenan.dev/how-the-software-development-life-cycle-helped-me</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[SDLC]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Tue, 12 Sep 2023 15:12:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694537528675/97c79e3d-fbe9-4f3d-abf3-089038a6faf2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While searching for better ways to plan a web project I found the the Software Development Lifecycle. This is a process that consists of several stages for building and running software applications. It is like a checklist of sorts, there are 6 stages in total, I used 5 of these as the final stage was not applicable.</p>
<ol>
<li><h3 id="heading-planning">Planning</h3>
</li>
</ol>
<p>The first phase of this lifecycle is the planning phase, here I set out the requirements of my website. What I wanted my website to do, how I thought I wanted my website to look. In simple terms, I made a plan for what I intended to use my website for.</p>
<ol>
<li><h3 id="heading-analysis">Analysis</h3>
</li>
</ol>
<p>The second phase looks at defining these requirements, I used user stories for this. This identified what I as the owner of the website wanted and why and also what users of the website may want and why. An example of this would be <em>“As a visitor of Rachael’s Recipes I want a navigation bar so that I can easily navigate the website.”</em>. This then creates an acceptance criteria or a task list of what should be done to adhere to this requirement. Throughout this stage and using the user stories I created a backlog of the documented requirements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694537264829/a5b1e69e-3927-4d7c-9549-4cf4765881fc.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-design">Design</h3>
</li>
</ol>
<p>The third stage of this life cycle is the designing phase. During this phase, I created a mock-up of my website. This gave me a visual of where to start and my end goal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694183848788/44674c31-1f2a-462a-a611-095e3f65c15e.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-implementation">Implementation</h3>
</li>
</ol>
<p>Stage four is the building stage, this is when I began to develop my website. I based my development process off the previous stage, using the requirements backlog as a guide to prioritising tasks that needed to be completed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694537140913/95a768f5-91f4-41b5-92ce-5de61f64b237.png" alt class="image--center mx-auto" /></p>
<ol>
<li><h3 id="heading-testing-and-integration">Testing and Integration</h3>
</li>
</ol>
<p>The final stage I used was the testing phase. This looked at all aspects of my website, making sure everything worked the way I wanted it to work and whether the website was visually how I wanted.</p>
<p>The final thing I looked at as part of my testing phase was how accessible my website was. I used the Google Lighthouse report to test my website. This report looks at the performance of the website, the accessibility, the best practices of the website and the search engine optimisation. This was very helpful in understanding how to better my website, as it gives you examples on how to fix specific issues such as font and background contrast for accessibility (see <a class="post-section-overview" href="#_Appendix_4_%E2%80%93"><strong>appendix 4</strong></a> for some report details).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694183911242/3d101e93-d42d-40a7-b12f-c47b27870bf8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694183930799/3ffa68e9-d2f7-4638-80cf-556c3bfcbabf.png" alt class="image--center mx-auto" /></p>
<p>Using the Software Development Lifecycle was an immense aid in creating a building my website, it provided a more structured outline for what needed to be completed.</p>
<p><strong>Cover image reference:</strong></p>
<p>WeeTech Solutions Pvt Ltd, 2023, "Software-Development-Life-Cycle" [Online], Available at: <a target="_blank" href="https://www.weetechsolution.com/wp-content/uploads/2022/12/Software-Development-Life-Cycle.png">https://www.weetechsolution.com/wp-content/uploads/2022/12/Software-Development-Life-Cycle.png</a> (Accessed: 12/09/2023)</p>
]]></content:encoded></item><item><title><![CDATA[My basic understanding of C# generics]]></title><description><![CDATA[Generic means a characteristic of or relating to a class or group of things; not specific, common, or general (Oxford Languages). In terms of C#, generic means not specific to a distinct data type.
Think of generics as a lunchbox, your lunchbox can h...]]></description><link>https://rachaelkeenan.dev/my-basic-understanding-of-c-generics</link><guid isPermaLink="true">https://rachaelkeenan.dev/my-basic-understanding-of-c-generics</guid><category><![CDATA[C#]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Fri, 08 Sep 2023 14:22:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/aDFj86NuvD8/upload/8a209438b55c002f4ff3afdd3cba9184.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Generic means a characteristic of or relating to a class or group of things; not specific, common, or general (Oxford Languages). In terms of C#, generic means not specific to a distinct data type.</p>
<p>Think of generics as a lunchbox, your lunchbox can hold different foods at different times. Meaning, your lunchbox is the class and the foods are the data types. This can be described as having a flexible container that can hold different data types, like strings, ints or even a custom type.</p>
<p>A generic class is written similar to the example below:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Lunchbox</span>&lt;<span class="hljs-title">T</span>&gt;
{
    ...
}
</code></pre>
<p>You would then build this class up with its properties, constructors and methods:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Lunchbox</span>&lt;<span class="hljs-title">T</span>&gt;
{
    <span class="hljs-comment">// Properties</span>
    <span class="hljs-keyword">private</span> T lunchItem;

    <span class="hljs-comment">// Constructors</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Lunchbox</span>(<span class="hljs-params">T newlunchItem</span>)</span>
    {
        lunchItem = newlunchItem;
    }

    <span class="hljs-comment">// Methods</span>
    <span class="hljs-keyword">public</span> T GetLunchItem
    {
        <span class="hljs-keyword">return</span> lunchItem
    }
}
</code></pre>
<p>Then in your main program, you would create a collection to store these various lunchbox foods:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Create a Lunchbox for sandwiches (string)</span>
        Lunchbox&lt;<span class="hljs-keyword">string</span>&gt; sandwichLunchbox = <span class="hljs-keyword">new</span> Lunchbox&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-string">"BLT"</span>, <span class="hljs-string">"Chicken and Stuffing"</span>, <span class="hljs-string">"Ham and Cheese"</span>);

        <span class="hljs-comment">// Get the items from the lunchbox</span>
        <span class="hljs-keyword">string</span> sandwich = sandwichLunchbox.GetLunchItem();

        <span class="hljs-comment">// Display the items from the lunchbox</span>
        Console.WriteLine(<span class="hljs-string">"Sandwich: "</span> + sandwich);
    }
}
</code></pre>
<h3 id="heading-why-use-generics">Why use generics?</h3>
<p>Reusability: It is reusable because you don't need a different class for each data type, the generic class allows for different inputs.</p>
<p>Safety: When you specify the data type you intend to use, you can only use this type of input. If you define a string for example, but input an int, a compile-time error will occur because it expects the defined type of string.</p>
<p>Flexibility: Generics are very flexible because they can adapt to various data types, even custom types.</p>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://www.tutorialsteacher.com/csharp/csharp-generics">https://www.tutorialsteacher.com/csharp/csharp-generics</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics">https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics</a></p>
</li>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/c-sharp-generics-introduction/">https://www.geeksforgeeks.org/c-sharp-generics-introduction/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Using the [Authorize] attribute]]></title><description><![CDATA[The [Authorize] attribute is a way to limit access to a particular section of your MVC controller or action to an authenticated user.
I came to find this attribute during a college project where I needed to restrict access to specific pages within my...]]></description><link>https://rachaelkeenan.dev/using-the-authorize-attribute</link><guid isPermaLink="true">https://rachaelkeenan.dev/using-the-authorize-attribute</guid><category><![CDATA[ASP.NET]]></category><category><![CDATA[mvc]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Wed, 06 Sep 2023 16:09:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/4RgivBMvkME/upload/43a8dfb7e1663dfe096e1a5c83986855.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>[Authorize]</code> attribute is a way to limit access to a particular section of your MVC controller or action to an authenticated user.</p>
<p>I came to find this attribute during a college project where I needed to restrict access to specific pages within my application to users who were logged in. I first attempted to redirect the page to an error page if the user was not logged in, however, this did not work and threw a runtime error, see <a target="_blank" href="https://rachael.hashnode.dev/custom-error-pages-for-http-status-codes-in-aspnet-mvc">Custom error pages for HTTP status codes in</a> <a target="_blank" href="http://ASP.NET">ASP.NET</a> <a target="_blank" href="https://rachael.hashnode.dev/custom-error-pages-for-http-status-codes-in-aspnet-mvc">MVC</a> for more information on creating custom error pages.</p>
<p>I instead used the <code>[Authorize]</code> attribute on certain actions within my relevant controller, see <a target="_blank" href="https://jakeydocs.readthedocs.io/en/latest/security/authorization/simple.html#simple-authorization">Simple Authorization</a> for more information on the <code>[Authorize]</code> attribute. For example, I used the <code>[Authorize]</code> to redirect a link to the login page if a user was not logged in. The redirect is simply a side-effect of the user not being signed in when trying to access a route (Controller action) that is decorated with an <code>[Authorize]</code> attribute. In doing this I did not have to redirect to an error page when a User was not logged in and I used the <code>[Authorize]</code> attribute in its most simple form.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Authorize</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> ActionResult <span class="hljs-title">AddToFavourites</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
{
     ...
}
</code></pre>
<p>The <code>[Authorize]</code> attribute can be used on the controller itself or each individual action. Using the <code>[Authorize]</code> attribute on the controller causes the MVC app to check if a user is logged in before carrying out any actions within the controller.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Authorize</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RecipesController</span> : <span class="hljs-title">Controller</span> 
{
     ...
}
</code></pre>
<p>I used the <code>[Authorize]</code> attribute very simply, on specific action methods, however upon my further learning into the <code>[Authorize]</code> I found that when using the attribute on the controller, you can use the <code>[AllowAnonymous]</code>. This <code>[AllowAnonymous]</code> attribute can be used to display certain pages to a user even if they are not logged in, such as the home page or the login page. This seems a better and cleaner way to use these attributes if most pages require authentication to view, however, if only one or two pages need authentication, using the <code>[Authorize]</code> attribute over each action method is simpler. For example, in my project I only needed to limit and edit a page and a favourites page, so using the <code>[Authorize]</code> attribute on the whole controller would not have made sense</p>
<p>Note: the <code>[Authorize]</code> attribute can be made more specific, for example, will only authorize named users <code>[Authorize(Users = “Mary, John”)]</code> or users with certain roles <code>[Authorize(Roles = “Admin”)]</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Filter data in an MVC application for a specific user]]></title><description><![CDATA[I created a recipe blog in ASP.NET MVC as part of a college project. This application used Entity Framework to retrieve and store data. As part of this, I had a list of all recipes and also a list of favourite recipes that a user can save and remove....]]></description><link>https://rachaelkeenan.dev/filter-data-in-an-mvc-application-for-a-specific-user</link><guid isPermaLink="true">https://rachaelkeenan.dev/filter-data-in-an-mvc-application-for-a-specific-user</guid><category><![CDATA[ASP.NET]]></category><category><![CDATA[entity framework]]></category><category><![CDATA[mvc]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Tue, 05 Sep 2023 16:43:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/uAzUg6_tMCo/upload/718ac8e334c8e65684b9a4e383877816.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I created a recipe blog in <code>ASP.NET MVC</code> as part of a college project. This application used <code>Entity Framework</code> to retrieve and store data. As part of this, I had a list of all recipes and also a list of favourite recipes that a user can save and remove.</p>
<p>I encountered a problem as part of this implementation. The favourites list was displaying the saved recipes of every user, whereas I wanted only the logged-in user’s recipes to be displayed.</p>
<p>For this, I needed to figure out how I could filter by the user ID and only display the relevant results to the user.</p>
<p>To solve this issue I was facing I decided to use <code>LINQ</code> to filter by the user’s ID in the favourites database. You will need the using statement <code>using Microsoft.AspNet.Identity;</code> to retrieve the <code>userId</code> because this is stored in a separate database on the local server. To get this to work I needed to create a variable to store the user id as the <code>GetUserId()</code> method does not work within the query. I then used this variable in the query to compare the user id’s.</p>
<p>See the code below for an example…</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Microsoft.AspNet.Identity;

<span class="hljs-function"><span class="hljs-keyword">public</span> ActionResult <span class="hljs-title">Index</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">var</span> userId = User.Identity.GetUserId();

            <span class="hljs-keyword">var</span> userFavourites = db.Favourites
                .Where(f =&gt; f.UserID == userId)
                .ToList();

            <span class="hljs-keyword">return</span> View(userFavourites);
        }
</code></pre>
<p>Using LINQ to filter the data allowed me to only display the results of a specific user. I could also use this method in other areas of my project such as deleting recipes from the database, so if a user added a recipe to the blog only they would be able to delete that recipe when logged in.</p>
<p>This method is beneficial if you want to give access to certain users to view only specified data.</p>
]]></content:encoded></item><item><title><![CDATA[Adding project dependencies in Visual Studio]]></title><description><![CDATA[I was following along a PluralSight course (Building a Real-world C# 10 Application by Filip Ekberg) when I needed to add a dependency to a project file from another project file. Intellisense would not pick up on what I wanted to add and manually ty...]]></description><link>https://rachaelkeenan.dev/adding-project-dependencies-in-visual-studio</link><guid isPermaLink="true">https://rachaelkeenan.dev/adding-project-dependencies-in-visual-studio</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[C#]]></category><category><![CDATA[visual studio]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Tue, 15 Aug 2023 16:34:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/cckf4TsHAuw/upload/095bb536c594ef027a8d12b28f0f8074.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was following along a PluralSight course (<a target="_blank" href="https://app.pluralsight.com/library/courses/c-sharp-10-building-real-world-application/table-of-contents">Building a Real-world C# 10 Application</a> by Filip Ekberg) when I needed to add a dependency to a project file from another project file. Intellisense would not pick up on what I wanted to add and manually typing the using statement would not work either. I needed to add a project dependency to the relevant file.</p>
<p>When you want to share code from one project file to another, you create a dependency. This allows the dependent project file to access code from the other project file. These dependencies could be written in the csproj file of the dependent project. See last image for an example of how this can be written.</p>
<p>The easiest way to carry this task out would be to drag the project file you want to reference into the dependencies of the project file that requires the dependency.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692117080227/699c8ee4-163f-4b0f-9552-d38d7197dbee.gif" alt class="image--center mx-auto" /></p>
<p>The second way to add a dependency would be to right-click on the project's dependencies and select “Add Project Reference…”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692116883034/eca995b9-de92-4c7a-82b3-2eeee98c3999.png" alt class="image--center mx-auto" /></p>
<p>This brings you to a screen that allows you to choose which projects you would like to add.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692116900975/ea09799f-a08b-4698-bd93-bfc1eec45fdb.png" alt class="image--center mx-auto" /></p>
<p>The project dependency can be seen under dependencies of the project under projects</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692116914648/76ad4ef1-5e6c-49b3-98ea-9c0500f9c4a9.png" alt class="image--center mx-auto" /></p>
<p>or in the csproj file</p>
<pre><code class="lang-csharp">&lt;ItemGroup&gt;
   &lt;ProjectReference Include=<span class="hljs-string">"..\Globomantics.Domain\Globomantics.Domain.csproj"</span> /&gt;
&lt;/ItemGroup&gt;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Why is the [ValidateAntiForgeryToken] attribute so important?]]></title><description><![CDATA[I was creating an MVC/Web API application with ASP.NET through a PluralSight course and I came across the [ValidateAntiForgeryToken] attribute. This was used throughout the course when using [HttpPost] requests on methods. I decided to dig a little d...]]></description><link>https://rachaelkeenan.dev/why-is-the-validateantiforgerytoken-attribute-so-important</link><guid isPermaLink="true">https://rachaelkeenan.dev/why-is-the-validateantiforgerytoken-attribute-so-important</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[mvc]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Mon, 07 Aug 2023 13:35:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zAhAUSdRLJ8/upload/241fc86d066f3c4edba1de738d3bdd65.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was creating an MVC/Web API application with ASP.NET through a PluralSight course and I came across the <code>[ValidateAntiForgeryToken]</code> attribute. This was used throughout the course when using <code>[HttpPost]</code> requests on methods. I decided to dig a little deeper into what this attribute was doing and why it is so important.</p>
<p>This attribute is used to prevent forgery on a request, the instance in which I used this attribute was with forms, to update a database. The <code>[ValidateAntiForgeryToken]</code> attribute is important with a post request because it uses cookies to validate your request, for example, if you want to insert data into a database using a form you want to make sure that the post request is secure and that it cannot be used maliciously on another web host. If you do not use the attribute you are susceptible to malicious attacks from outsiders, this can be dangerous if these requests include personal data and could be used anywhere in the world because it does not use anything to validate the request.</p>
<p>I did some tests to understand how this works using a <code>localhost</code> server.</p>
<h4 id="heading-test-1">Test 1</h4>
<p>For my first test, I removed the {ValidateAntiForgeryToken] attribute from my create method. By doing this I was able to create multiple instances of the same record without any validation using a <code>localhost</code> server. This is a small way to test this, but it made it clear that this could be very dangerous on other servers that are more open. Meaning someone could potentially steal personal data if the site being used is not using appropriate anti-forgery options.</p>
<p>The image below shows the request being sent again with the same cookie. This request will work whether the cookies match or not and if there is no cookie in the browser at all.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681481001198/da4c1f15-3256-49f9-90ec-e07385cc1c6d.png" alt class="image--center mx-auto" /></p>
<p>This image shows the two entries created which are the same because the code is not using the <code>[ValidateAntiForgeryToken]</code> attribute.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681481021430/35c36b93-f3a4-48ac-809f-50749400bafa.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-test-2">Test 2</h4>
<p>Test 2 uses the <code>[ValidateAntiForgeryToken]</code> and is split into two parts, the first is deleting the cookie and then sending a request to create a data entry. This throws an error "The required anti-forgery cookie '__RequestVerificationToken' is not present".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681481247605/4cad07da-39fe-4917-828c-d9631e9b10a0.png" alt class="image--center mx-auto" /></p>
<p>This is because as the request is running, the browser is trying to match the cookies to accept the request. Because the cookie has been deleted from the browser, the cookie from the request cannot be matched to the browser's cookie and the request to create is denied.</p>
<p>The second part of the test involved altering the cookie definition from the browser and sending a create request, again because these two cookies cannot be matched the browser denies the request. The error thrown is "The anti-forgery token could not be decrypted..."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681481292382/820e428d-191d-4831-bce4-242b1b8f7e51.png" alt class="image--center mx-auto" /></p>
<p>From this, I have concluded that not including an [ValidateAntiForgeryToken] attribute leaves a web application open to malicious behaviour, and could potentially distribute personal information of customers because of this. While I can acknowledge that there may be better ways to use this attribute or different ways to prevent this type of security breach, this is my learning to date.</p>
<p>A potentially better way to use the anti-forgery token, if you are using <code>.NET Core</code>, is to use the <code>[AutoValidateAntiForgeryTokenAttribute]</code>. This can be applied to the whole controller and will validate all unsafe methods such as <code>Post, Put, Patch and Delete</code>. However, it will ignore methods such as <code>Get, Head, Options and Trace</code>, so if you want to use validation you will have to use the <code>[ValidateAntiForgeryToken]</code> over these methods.</p>
<p><a target="_blank" href="https://stackoverflow.com/questions/39947460/autovalidateantiforgerytoken-vs-validateantiforgerytoken">https://stackoverflow.com/questions/39947460/autovalidateantiforgerytoken-vs-validateantiforgerytoken</a></p>
]]></content:encoded></item><item><title><![CDATA[Custom error pages for HTTP status codes in ASP.NET MVC]]></title><description><![CDATA[Background
I encountered a problem with my custom error pages when completing a college project. I had 2 HTTP errors which I wanted to use a custom error page for, “404 - Not Found” and “401 - Unauthorized”. To create these custom errors, I first cre...]]></description><link>https://rachaelkeenan.dev/custom-error-pages-for-http-status-codes-in-aspnet-mvc</link><guid isPermaLink="true">https://rachaelkeenan.dev/custom-error-pages-for-http-status-codes-in-aspnet-mvc</guid><category><![CDATA[mvc]]></category><category><![CDATA[C#]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[ASP.NET]]></category><dc:creator><![CDATA[Rachael Keenan]]></dc:creator><pubDate>Wed, 14 Jun 2023 16:11:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/RMIsZlv8qv4/upload/ecdcdd8554fbf010b036d48f41b8da7e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-background">Background</h3>
<p>I encountered a problem with my custom error pages when completing a college project. I had 2 <code>HTTP errors</code> which I wanted to use a custom error page for, “404 - Not Found” and “401 - Unauthorized”. To create these custom errors, I first created an “Error” controller and then made an <code>ActionResult</code> method for each error, within this controller and created views for the errors from these methods. The 404 error worked, whereby if an ID was not used in the URL or did not exist, a custom 404 error page was displayed to the user. However, the 401 error I intended to use when a user tried to access certain links/pages when they were not logged in was throwing a runtime error instead of my custom error page.</p>
<h3 id="heading-creating-a-custom-error-page-in-mvc">Creating a custom Error page in MVC</h3>
<p>Creating a custom error page is relatively simple. Do note that there is already an <code>Error.cshtml</code> view available in the <code>/Shared/Views</code> folder with the default <a target="_blank" href="http://ASP.NET">ASP.NET</a> MVC template.</p>
<ol>
<li><p>Create a Controller for the custom error(s) you want to use, I named my controller <code>ErrorController</code>.</p>
</li>
<li><p>Inside this controller you will need a method that returns <code>ActionResult</code> for each error.</p>
<pre><code class="lang-csharp"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ErrorController</span> : <span class="hljs-title">Controller</span>
 {
     <span class="hljs-comment">// GET: Error</span>
     <span class="hljs-function"><span class="hljs-keyword">public</span> ActionResult <span class="hljs-title">NotFound</span>(<span class="hljs-params"></span>)</span>
     {
         Response.StatusCode = <span class="hljs-number">404</span>;
         <span class="hljs-keyword">return</span> View();
     }

     <span class="hljs-comment">// GET: Error</span>
     <span class="hljs-function"><span class="hljs-keyword">public</span> ActionResult <span class="hljs-title">BadRequest</span>(<span class="hljs-params"></span>)</span>
     {
         Response.StatusCode = <span class="hljs-number">400</span>;
         <span class="hljs-keyword">return</span> View();
     }
 }
</code></pre>
</li>
<li><p>The next step is creating the relevant views for each error. You can do this by right-clicking on the method name, ie. NotFound and selecting the <code>“Add View”</code> option.</p>
</li>
<li><p>Update the information in this view to whatever you want your error page to tell the user.</p>
</li>
<li><p>Next, open the <code>Web.config</code> file for your MVC application, make sure to choose the correct file as there is a <code>Web.config</code> file in the Views folder (you do not want this file).</p>
</li>
<li><p>In the <code>Web.config</code> file find the <code>&lt;system.web&gt;</code> attribute. Within this attribute add a <code>&lt;customErrors&gt;</code> attribute with <code>mode=”On”</code> . See below for an example…</p>
<pre><code class="lang-csharp"> &lt;customErrors mode=<span class="hljs-string">"On"</span>&gt;
     &lt;error statusCode=<span class="hljs-string">"400"</span> redirect=<span class="hljs-string">"/Error/BadRequest"</span>/&gt;
     &lt;error statusCode=<span class="hljs-string">"404"</span> redirect=<span class="hljs-string">"/Error/NotFound"</span>/&gt;
 &lt;/customErrors&gt;
</code></pre>
</li>
<li><p>Open the <code>Global.asax</code> file for your MVC application and in this add the <code>HandleErrorAttibute</code>. The last line in the example is what you will need to add, your code should look something like this.</p>
<pre><code class="lang-csharp"> <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Application_Start</span>(<span class="hljs-params"></span>)</span>
 {
     AreaRegistration.RegisterAllAreas();
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
     RouteConfig.RegisterRoutes(RouteTable.Routes);
     BundleConfig.RegisterBundles(BundleTable.Bundles);

         GlobalFilters.Filters.Add(<span class="hljs-keyword">new</span> HandleErrorAttribute());
 }
</code></pre>
</li>
<li><p>Lastly, update your exceptions in the relevant controllers. Your exception will look similar to this depending on your error code.</p>
<pre><code class="lang-csharp"> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HttpException(<span class="hljs-number">404</span>, <span class="hljs-string">"Not Found"</span>);
</code></pre>
</li>
</ol>
<h3 id="heading-solution">Solution</h3>
<p>Because my 401 error code would not work for my intended purpose I instead used the <code>[Authorize]</code> attribute on certain actions within my relevant controller, see <a target="_blank" href="https://jakeydocs.readthedocs.io/en/latest/security/authorization/simple.html#simple-authorization">Simple Authorization</a> for more information on the <code>[Authorize]</code> attribute. For example, I used the <code>[Authorize]</code> attribute to redirect a link to the login page if a user was not logged in. The redirect here is simply a side-effect of the user not being signed in when trying to access a route (Controller action) that is decorated with an <code>[Authorize]</code> attribute. In doing this I did not have to redirect to an error page when a User was not logged in and the <code>[Authorize]</code> attribute was used in its simplest form.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Authorize</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> ActionResult <span class="hljs-title">AddToFavourites</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
{
}
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In conclusion, my error for code 401 not working was a good thing. This helped me search for alternative solutions to a problem, which led me to the <code>[Authorize]</code> attribute, which turned out to be a better fit for what I wanted.</p>
]]></content:encoded></item></channel></rss>