<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2018 on Funky Si's Blog (Dev)</title><link>https://blog-dev.funkysi1701.com/2018/</link><description>Recent content in 2018 on Funky Si's Blog (Dev)</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Thu, 27 Dec 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://blog-dev.funkysi1701.com/2018/index.xml" rel="self" type="application/rss+xml"/><item><title>Looking back at 2018</title><link>https://blog-dev.funkysi1701.com/posts/2018/looking-back-at-2018/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Thu, 27 Dec 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/looking-back-at-2018/</guid><category term="C-Sharp">C-Sharp</category><category term="Home">Home</category><category term="Family">Family</category><category term="Goals">Goals</category><description>&lt;p&gt;As 2018 starts to draw to a close let’s look at some of the highlights from the past year.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;New Home - I started 2018 with the goal of buying my own home and I managed it. At the end of October I actually moved in but it was months of looking at houses, speaking to estate agents, saving, packing and unpacking. There is more I want to do to my home in 2019 so this is only really the beginning.&lt;/li&gt;
&lt;li&gt;New Job - Another goal was to kick my career up a notch and this happened in June. It has been great working as part of a large team and I have learnt loads, there is much more I want to learn and contribute to so 2019 should be great on that front.&lt;/li&gt;
&lt;li&gt;New Car - Not a goal that I achieved as unfortunately in October I was involved in a car accident, no one was seriously hurt but this was a horrible experience to go through. My car was written off which gave me an excuse to buy a new car.&lt;/li&gt;
&lt;li&gt;See more of family was a goal, I am not sure if I really achieved this. However family have been around loads for us during our move and we do live closer so hopefully I can work on this some more.&lt;/li&gt;
&lt;li&gt;Celebrate 5 years of marriage. It hasn&amp;rsquo;t been an easy year for me and the wife due to moving house and all the stress that involved plus with two children she was diagnosed with Postnatal Depression which as a family we are still dealing with. All that said we had a fab weekend away and we so need to do something similar again soon.&lt;/li&gt;
&lt;li&gt;Family. 2018 has included many great times with my two boys. It&amp;rsquo;s been amazing seeing them grow, in September we had a thanksgiving service for them and in July we had our annual holiday.&lt;/li&gt;
&lt;li&gt;Lightning Talk. This is the only thing I mentioned as a goal that didn&amp;rsquo;t happen, it&amp;rsquo;s on my 2019 list so hopefully I can kick myself into action but with everything else I achieved something had to slip.   &lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Run SQL Server in a Linux container</title><link>https://blog-dev.funkysi1701.com/posts/2018/running-sql-server-on-a-linux-container-using-docker-for-windows/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 05 Nov 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/running-sql-server-on-a-linux-container-using-docker-for-windows/</guid><category term="Windows">Windows</category><category term="Docker">Docker</category><category term="SQL">SQL</category><category term="Linux">Linux</category><description>&lt;p&gt;Recently I have been investigating what all the fuss is about Docker and it has been well worth my time as Docker is pretty awesome for automating stuff.&lt;/p&gt;
&lt;p&gt;My development environment has typically required installing SQL Server. SQL is a bit of a beast with lots of options and takes time to setup how you want.&lt;/p&gt;
&lt;p&gt;However since Microsoft have now created a version of SQL Server that runs on Linux you can run SQL Server in a Linux container with only a few commands.&lt;/p&gt;
&lt;p&gt;I am going to assume you already have Docker for windows installed on your development machine. If not head over to &lt;a href="https://docs.docker.com/docker-for-windows/install/#where-to-go-next" target="_blank" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;
and find out how.&lt;/p&gt;
&lt;p&gt;The Microsoft guide to setting up SQL Server in a Linux container can be found &lt;a href="https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017" target="_blank" rel="noopener noreferrer"&gt;here&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;First you need to download the image. In a powershell window run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker pull mcr.microsoft.com/mssql/server:2017-latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This downloads the latest sql server image.&lt;/p&gt;
&lt;p&gt;To run this image run the following:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -e &amp;#34;ACCEPT_EULA=Y&amp;#34; -e &amp;#34;SA_PASSWORD=password&amp;#34;
-p 1433:1433 --name sql
-d mcr.microsoft.com/mssql/server:2017-latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To run a SQL Server image you are required to accept the terms and conditions and set a default sa password. These are added as environment variables with the -e flag.&lt;/p&gt;
&lt;p&gt;You also need to set the ports that your container will run on (1433 is the default SQL port) and give your container a name, in this case &amp;ldquo;sql&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;If you have already installed SQL Server you will not be able to run the container on the same port as your local install. To solve this you can select a different port.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -e &amp;#34;ACCEPT_EULA=Y&amp;#34; -e &amp;#34;SA_PASSWORD=password&amp;#34;
-p 1434:1433 --name sql
-d mcr.microsoft.com/mssql/server:2017-latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;-p 1434:1433 maps the 1433 port on the container to port 1434 of your local environment.&lt;/p&gt;
&lt;p&gt;Once you have run this command you can connect SQL Server Management Studio (SSMS) to (local) or (local),1434 if you are using a different port using the credentials you provided and execute any SQL you like.&lt;/p&gt;
&lt;p&gt;If your development environment requires windows authentication this of course is not for you, if it doesn’t you are good to go.&lt;/p&gt;
&lt;p&gt;The development environment I have been using has various powershell scripts for setting things up. These assume windows auth. However I have adapted them to take custom credentials.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$credential = Get-Credential $server.ConnectionContext.LoginSecure=$false
$server.ConnectionContext.set_Login($credential.UserName)
$server.ConnectionContext.set_SecurePassword($credential.Password)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The Get-Credential command creates a dialog where you can enter SQL credentials, this is then stored in a variable and used in the rest of the script.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I restore a backup file to my container?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker exec -it sql mkdir /var/opt/mssql/backup
docker cp database.bak sql:/var/opt/mssql/backup
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This creates a backup folder and copies a backup file from your local environment to the container. You can then use management studio to restore the backup file (or you could write a sql script to do it). One thing to note when restoring databases, make sure the files are restored to Linux locations not windows locations.&lt;/p&gt;
&lt;p&gt;The only issues I have encountered so far are the lack of support for SSIS packages and no windows auth. There are sql server windows images available which I haven’t tried yet which may work better with some of these options.&lt;/p&gt;</description></item><item><title>2018 The Story So far</title><link>https://blog-dev.funkysi1701.com/posts/2018/2018-the-story-so-far/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Sat, 28 Jul 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/2018-the-story-so-far/</guid><category term="Career">Career</category><category term="Home">Home</category><category term="Family">Family</category><category term="Job">Job</category><category term="Goals">Goals</category><description>&lt;p&gt;Remember me? I used to write blog posts but somehow life got in the way. So much has happened this year, lets have a look at my &lt;a href="https://blog-dev.funkysi1701.com/posts/2018/lets-see-2018-can"&gt;goals&lt;/a&gt;
for 2018 and see how far we have got with them.&lt;/p&gt;
&lt;h2 id="buy-a-house"&gt;Buy a house&lt;a class="anchor ms-1" href="#buy-a-house" aria-label="Permalink: Buy a house"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My first goal for 2018 was to buy a house. Well so much progress has been made with this goal.&lt;/p&gt;
&lt;p&gt;We looked at a few houses, and have made an offer, had it accepted and are waiting for the last few things to get arranged before we start arranging to move in.&lt;/p&gt;
&lt;p&gt;The location we decided upon was &lt;a href="https://www.google.co.uk/maps/place/Thorne,&amp;#43;Doncaster/" target="_blank" rel="noopener noreferrer"&gt;Thorne&lt;/a&gt;
. This is about an hour from York where most of our friends are and my wife has lived all her life, and also an hour from where my family live. I have tried my best to balance location and size of property and we think our new home is going to be a good balance but only time will tell.&lt;/p&gt;
&lt;p&gt;I have a bit of a mammoth time ahead of me getting everything we own packed up and moved to our new home so wish me luck, but we will get there it is just going to be hard work.&lt;/p&gt;
&lt;h2 id="new-job"&gt;New Job&lt;a class="anchor ms-1" href="#new-job" aria-label="Permalink: New Job"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In June 2018 I started a new job. This was slightly later than I had hoped but I believe it has been worth the wait.&lt;/p&gt;
&lt;p&gt;My new job has lots of perks. Finish early on a Friday (1pm), On site canteen, Cool air-conditioned office, Flexible working hours, Part of a big development team.&lt;/p&gt;
&lt;p&gt;The main benefit is that I am part of a big development team. I have a huge list of things to learn both in terms of technology and how large development teams function. The team is about to finish the first sprint that I have contributed to. My contributions have been very small. A bug fix here, a tweak of an API there. But the important thing is that I am making a contribution and learning along the way.&lt;/p&gt;
&lt;p&gt;I have also started asking questions about deployment and how this could be automated. Something that interests me, especially with the sysadmin and devops background. I have been tasked with learning &lt;a href="https://docs.docker.com/" target="_blank" rel="noopener noreferrer"&gt;docker&lt;/a&gt;
, so expect some blog posts on this topic in the near future.&lt;/p&gt;
&lt;h2 id="see-more-of-family"&gt;See more of family&lt;a class="anchor ms-1" href="#see-more-of-family" aria-label="Permalink: See more of family"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This one I am going to count as a miss. I have seen family a few times this year, but my efforts have been more on the first two items in this list. Hopefully this will change as things settle down.&lt;/p&gt;
&lt;h2 id="celebrate-5-years-of-marriage"&gt;Celebrate 5 years of Marriage&lt;a class="anchor ms-1" href="#celebrate-5-years-of-marriage" aria-label="Permalink: Celebrate 5 years of Marriage"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Me and the wife had a great weekend away to celebrate our wedding anniversary.&lt;/p&gt;
&lt;h2 id="celebrate-my-two-children"&gt;Celebrate my two children&lt;a class="anchor ms-1" href="#celebrate-my-two-children" aria-label="Permalink: Celebrate my two children"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not happened yet but it is booked and we just need to arrange a few more details.&lt;/p&gt;
&lt;h2 id="lightning-talk"&gt;Lightning Talk&lt;a class="anchor ms-1" href="#lightning-talk" aria-label="Permalink: Lightning Talk"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have made no effort to do a talk and this is going to be a goal for 2019 I think. Most of the reason is concentrating on the other areas above, but also because I am not a natural speaker and I don’t like stepping out of my comfort zone. But I will do it, I just need to wait for other things to calm down a bit first.&lt;/p&gt;
&lt;h2 id="family-holiday"&gt;Family Holiday&lt;a class="anchor ms-1" href="#family-holiday" aria-label="Permalink: Family Holiday"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We had a great week away at the start of July. The weather was really great (and still is) and we had lots of time doing things as a family.&lt;/p&gt;</description></item><item><title>Casting and Converting between types</title><link>https://blog-dev.funkysi1701.com/posts/2018/casting-and-converting-between-types/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 07 May 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/casting-and-converting-between-types/</guid><category term="C-Sharp">C-Sharp</category><category term="Casting">Casting</category><category term="Convert">Convert</category><description>&lt;p&gt;Recently I was asked how to convert a number to a string. Let&amp;rsquo;s look at a few ways of approaching this problem.&lt;/p&gt;
&lt;p&gt;Most objects in c# have a method called ToString() which displays the string representation of that object. This is because of inheritance, all objects inherit from System.Object which defines ToString().&lt;/p&gt;
&lt;p&gt;Int32 is a struct so it inherits from System.ValueType which also inherits from System.Object&lt;/p&gt;
&lt;p&gt;so in code&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a = &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; b = a.ToString();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s look at the reverse. However the reverse runs the risk of throwing an error, let&amp;rsquo;s look at why.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; b = &lt;span style="color:#e6db74"&gt;&amp;#34;9&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; c = &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; d = &lt;span style="color:#e6db74"&gt;&amp;#34;two&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All are valid strings but only one can be converted to a number. Use the TryParse method to convert to a number.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;.TryParse(&lt;span style="color:#e6db74"&gt;&amp;#34;9&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; e);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TryParse will not throw an exception if the conversion fails, if it succeeds variable e will contain the result. Note an earlier version of c# required you to define the out parameter before using it with TryParse.&lt;/p&gt;
&lt;p&gt;int.Parse exists to do the same thing however it will throw exceptions if a conversion is not possible. The same is true if you use Convert.ToInt32(&amp;ldquo;two&amp;rdquo;);&lt;/p&gt;
&lt;h2 id="casting"&gt;Casting&lt;a class="anchor ms-1" href="#casting" aria-label="Permalink: Casting"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Casting is a way to explicitly telling the compiler that a type is actually another type and you are aware data loss will occur.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;double&lt;/span&gt; x = &lt;span style="color:#ae81ff"&gt;4.5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; y = (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)x;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However it is not possible to cast a string to a number format as a string can contain any character not just number characters.&lt;/p&gt;</description></item><item><title>Let’s Encrypt is awesome</title><link>https://blog-dev.funkysi1701.com/posts/2018/lets-encrypt-is-awesome/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 30 Apr 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/lets-encrypt-is-awesome/</guid><category term="DevOps">DevOps</category><category term="SSL">SSL</category><category term="Security">Security</category><description>&lt;p&gt;Let’s Encrypt is a free way to get a SSL certificate onto your website and until recently I had never tried it. It is very easy and I think it is awesome.&lt;/p&gt;
&lt;p&gt;IIS is the web server software the Microsoft include with Windows 10 and Windows Server. I have it installed on my laptop and it displays the default IIS page.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Default welcome page for IIS on Windows" src="https://blog-dev.funkysi1701.com/images/2018/iis.jpg" loading="lazy"
width="2170" height="1311"
/&gt;
&lt;/p&gt;
&lt;p&gt;It is not really a good idea to host websites on your laptop, use a dedicated web server, or host with a hosting company, however the techniques are the same and it gives me something to write about!&lt;/p&gt;
&lt;p&gt;In order to point a domain name at what IIS on my machine was serving up I did the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do a google search for “whats my IP”, this will return your public IP. Most residential ISPs use dynamic IPs so it may change over time, (which is another reason not to host a website on your laptop!)&lt;/li&gt;
&lt;li&gt;Add an A record on a domain with the IP address you have just got&lt;/li&gt;
&lt;li&gt;Your public IP most likely points at your router not your laptop so enable port forwarding of port 80 and port 443 to the internal IP of your laptop (something like 192.168.0.11 etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now comes the fun Let’s Encrypt stuff!&lt;/p&gt;
&lt;p&gt;First you need a Let’s Encrypt client, there are a lot of them out there mostly for linux flavours, however a bit of googling found a windows one. Go to &lt;a href="https://github.com/PKISharp/win-acme/releases" target="_blank" rel="noopener noreferrer"&gt;https://github.com/PKISharp/win-acme/releases&lt;/a&gt;
and download the zip file and unzip it.&lt;/p&gt;
&lt;p&gt;Run the executable from the zip file and follow the onscreen prompts.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="win-acme client prompt to create a new Let&amp;rsquo;s Encrypt certificate" src="https://blog-dev.funkysi1701.com/images/2018/letsencrypt.jpg" loading="lazy"
width="1174" height="733"
/&gt;
&lt;/p&gt;
&lt;p&gt;Press N to create a new certificate.&lt;/p&gt;
&lt;p&gt;Then press 1 to bind to single website found in your IIS setup&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="win-acme client prompt to bind a certificate to an IIS website" src="https://blog-dev.funkysi1701.com/images/2018/letsencrypt2.jpg" loading="lazy"
width="1147" height="1024"
/&gt;
&lt;/p&gt;
&lt;p&gt;And now magically Let’s Encrypt knows what you have setup in IIS.&lt;/p&gt;
&lt;p&gt;Now all you need to do is enter an email address incase a renewal fails and agree to the let’s encrypt terms and you are all setup.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="win-acme client confirming Let&amp;rsquo;s Encrypt certificate setup" src="https://blog-dev.funkysi1701.com/images/2018/letsencrypt3.jpg" loading="lazy"
width="957" height="1147"
/&gt;
&lt;/p&gt;
&lt;p&gt;How awesome and easy is that for getting your websites working with a SSL certificate. If you have IIS configured on a server, give it a try and you can SSL all your things.&lt;/p&gt;</description></item><item><title>DNS for Developers</title><link>https://blog-dev.funkysi1701.com/posts/2018/dns-for-developers/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 09 Apr 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/dns-for-developers/</guid><category term="DNS">DNS</category><category term="DevOps">DevOps</category><description>&lt;p&gt;DNS is the backbone of the internet and as such I believe every developer should know something about the basics and not just leave it for the sysadmin to sort.&lt;/p&gt;
&lt;h2 id="what-is-dns"&gt;What is DNS?&lt;a class="anchor ms-1" href="#what-is-dns" aria-label="Permalink: What is DNS?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;DNS or Domain Name System is what translates Domain names to IP addresses and vice versa.&lt;/p&gt;
&lt;h2 id="wait-what-is-an-ip-address-and-what-are-domain-names"&gt;Wait what is an IP address and what are domain names?&lt;a class="anchor ms-1" href="#wait-what-is-an-ip-address-and-what-are-domain-names" aria-label="Permalink: Wait what is an IP address and what are domain names?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You do realise this is a developer blog? An IP address is a unique address on the internet and a domain name is a user friendly label for one or more of these.&lt;/p&gt;
&lt;p&gt;An example might be google.com which for me resolves to 216.58.204.14&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;a class="anchor ms-1" href="#how-it-works" aria-label="Permalink: How it works"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="DNS lookup flow diagram showing how a browser resolves a domain name" src="https://blog-dev.funkysi1701.com/images/2018/dns-rev-1.gif" loading="lazy"
width="360" height="320"
/&gt;
When your browser makes a request to google.com it makes a request to your ISPs DNS Servers. This resolves google.com to 216.58.204.14&lt;/p&gt;
&lt;p&gt;In more detail your ISPs DNS server will forward the DNS query to another DNS server and will cache the results for a set amount of time. This is the TTL or Time To Live. Next time the ISP DNS Server will be able to reply directly without needing to forward requests.&lt;/p&gt;
&lt;p&gt;This forwarding and caching is what makes making a DNS change not instantaneous. The TTL needs to be reached so that no results are still being fetched from the cache of DNS servers across the globe.&lt;/p&gt;
&lt;h2 id="dns-records"&gt;DNS Records&lt;a class="anchor ms-1" href="#dns-records" aria-label="Permalink: DNS Records"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now we know roughly how DNS works let’s look at the most common type of records&lt;/p&gt;
&lt;h3 id="a"&gt;A&lt;a class="anchor ms-1" href="#a" aria-label="Permalink: A"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A (Host) records are the most simple records which translate domain names to IPs&lt;/p&gt;
&lt;p&gt;eg &lt;a href="https://www.google.com" target="_blank" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt;
to 216.58.204.14&lt;/p&gt;
&lt;h3 id="cname"&gt;CNAME&lt;a class="anchor ms-1" href="#cname" aria-label="Permalink: CNAME"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A CNAME (Canonical Name) record is different to an A record in that it maps a domain name to another domain name when no A record exists.&lt;/p&gt;
&lt;p&gt;eg &lt;a href="https://www.google.com" target="_blank" rel="noopener noreferrer"&gt;www.google.com&lt;/a&gt;
to somethingelse.google.com&lt;/p&gt;
&lt;p&gt;Typically Azure makes use of CNAMEs for many of its services especially adding a custom domain name&lt;/p&gt;
&lt;h3 id="mx"&gt;MX&lt;a class="anchor ms-1" href="#mx" aria-label="Permalink: MX"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MX stands for Mail Exchange and is used for configuring email&lt;/p&gt;
&lt;h3 id="name-server"&gt;Name Server&lt;a class="anchor ms-1" href="#name-server" aria-label="Permalink: Name Server"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Every domain has a number of Name Servers which tells you what servers control the DNS settings for that domain. If you change your Name Servers then the new Name servers will be where you can change your DNS settings.&lt;/p&gt;
&lt;p&gt;If you want to use a service like &lt;a href="https://dnsimple.com/" target="_blank" rel="noopener noreferrer"&gt;DNSimple&lt;/a&gt;
instead of &lt;a href="https://www.123-reg.co.uk/" target="_blank" rel="noopener noreferrer"&gt;123reg&lt;/a&gt;
or where ever you registered your domain then all you need to do is change your Name servers.&lt;/p&gt;
&lt;h3 id="aaaa"&gt;AAAA&lt;a class="anchor ms-1" href="#aaaa" aria-label="Permalink: AAAA"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Like A record but for ipv6&lt;/p&gt;
&lt;h2 id="what-next"&gt;What next?&lt;a class="anchor ms-1" href="#what-next" aria-label="Permalink: What next?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Want to put some different DNS records into practise? Buy a domain name and publish some content to it. Check out my previous post about &lt;a href="https://www.funkysi1701.com/posts/2017/creating-dns-records-programmatically/" target="_blank" rel="noopener noreferrer"&gt;programmatically adding records&lt;/a&gt;
. Want an SSL certificate? Get a wildcard one and then you can apply it to any subdomain you add to your domain.&lt;/p&gt;
&lt;p&gt;If you have a new website you want to publish consider which of the following is better:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://www.example.com/newsite&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://newsite.example.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I much prefer the second option, it looks cleaner, there is no potential conflict with the parent site, no subfolder issues between production and development.&lt;/p&gt;</description></item><item><title>Code Reviews</title><link>https://blog-dev.funkysi1701.com/posts/2018/codereviews/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 02 Apr 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/codereviews/</guid><category term="Git">Git</category><category term="VisualStudio">VisualStudio</category><description>&lt;p&gt;Reviewing code is a great habit to get into. Code reviews help share knowledge between your team members and help catch bugs before they get into production. But how do you get into the habit of reviewing and avoid the we don’t have time to do this mentality?&lt;/p&gt;
&lt;p&gt;Visual Studio Team Services (VSTS) has some great options that can help make code reviews second nature.&lt;/p&gt;
&lt;h2 id="pull-requests"&gt;Pull Requests&lt;a class="anchor ms-1" href="#pull-requests" aria-label="Permalink: Pull Requests"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A lot of source control systems have the concept of pull requests. This is where you request others to review your code usually in a branch and if they approve it, merge it into a main branch.&lt;/p&gt;
&lt;p&gt;To create a pull request in VSTS go to the Code section and select Pull Requests. Often VSTS will make a suggestion of what branch to make a pull request for, if you don’t see this just click the New Pull request button.&lt;/p&gt;
&lt;p&gt;Select a branch you want to merge from and a branch that should be merged into (usually you merge into master from a feature branch). Give your pull request a title and description and select who should review your code, this can either be an individual or a group of people. You can also review all the changes that will be reviewed so you can make any last minute changes before it is reviewed.&lt;/p&gt;
&lt;p&gt;Now if you are anything like me you want your code merged in as soon as you have created your pull request and there is nothing stopping you reviewing your own code and clicking approve and merge on your own pull request. However &lt;a href="https://docs.microsoft.com/en-us/vsts/git/branch-policies?view=vsts" target="_blank" rel="noopener noreferrer"&gt;branch policies&lt;/a&gt;
is a way around this problem.&lt;/p&gt;
&lt;h2 id="branch-policies"&gt;Branch Policies&lt;a class="anchor ms-1" href="#branch-policies" aria-label="Permalink: Branch Policies"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Branch Policy" src="https://blog-dev.funkysi1701.com/images/2018/save-policy-changes.png" loading="lazy"
width="599" height="901"
/&gt;
&lt;/p&gt;
&lt;p&gt;Branch policies allow you to specify how your code gets merged in.&lt;/p&gt;
&lt;p&gt;Go to the list of branches in VSTS and select branch policy and you will see a whole host of options to customise the merge process. If you do this on the master branch you will not be able to commit any changes to master without it going through a pull request.&lt;/p&gt;
&lt;p&gt;The first option enables you to select how many reviewers are needed on your code. If no one else works on your project best not setting this, but for everyone else setting at least one person to review your code is a great practice.&lt;/p&gt;
&lt;p&gt;Next you can ensure that your pull request is linked to a work item, this helps keep ensure you are actually fixing issues and not just making change for the sake of it.&lt;/p&gt;
&lt;p&gt;Check for comment resolution is a good setting to enable. This ensures that if your reviewer has commented about you needing to change this line here, it ensures that you do.&lt;/p&gt;
&lt;p&gt;Enforce merge strategy allows you to choose between fast forward merge or squash merge.&lt;/p&gt;
&lt;p&gt;Build validation enables the code to be built using a build definition you have configured. This is a great way to check code builds or tests pass before it gets merged in.&lt;/p&gt;
&lt;p&gt;The last two options allow you to specify code reviewers and third party external services.&lt;/p&gt;</description></item><item><title>Android Development Options</title><link>https://blog-dev.funkysi1701.com/posts/2018/android-development-options/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 26 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/android-development-options/</guid><category term="Cordova">Cordova</category><category term="Android">Android</category><category term="CrossPlatform">CrossPlatform</category><category term="Manifest">Manifest</category><category term="Xamarin">Xamarin</category><description>&lt;p&gt;A friend asked me how to get started in Android Development and I thought I might have a go at answering that question here.&lt;/p&gt;
&lt;p&gt;I am by no means an expert in Android development, I do have an app in the play store so I know something.&lt;/p&gt;
&lt;h2 id="manifest-file"&gt;Manifest File&lt;a class="anchor ms-1" href="#manifest-file" aria-label="Permalink: Manifest File"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is probably the easiest option and also doesn’t actually create an android app so I am not sure if it should be included in this list of not.&lt;/p&gt;
&lt;p&gt;If you have a website and you want to create an app for that you could just create a manifest file and add this to your website.&lt;/p&gt;
&lt;p&gt;Once your website has a manifest file, if you visit your website using a mobile phone or tablet you will get the option to add a shortcut to the home screen. You then have an app like experience in that you can click an icon to launch your website.&lt;/p&gt;
&lt;p&gt;A manifest file is a simple text file which specifies a few settings like the icon size, filename, what page loads when clicked and name of your “app”&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developers.google.com/web/fundamentals/web-app-manifest/" target="_blank" rel="noopener noreferrer"&gt;More information&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="visual-studio"&gt;Visual Studio&lt;a class="anchor ms-1" href="#visual-studio" aria-label="Permalink: Visual Studio"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the option I know most about as is what I have used.&lt;/p&gt;
&lt;p&gt;If you are familiar with Visual Studio you can use the Xamarin Forms software to create your app in C#. Xamarin Forms allows you to easily create cross platform apps that run on Android, IOS and windows phone. So far I have only experimented with Android but it should be relatively easy to extend my code to run on other platforms.&lt;/p&gt;
&lt;p&gt;Xamarin Forms allows you to write one a single codebase that can be compiled to run on the different platforms. Xamarin requires the use of XAML a XML like markup language for designing UI elements.&lt;/p&gt;
&lt;p&gt;More Information on &lt;a href="https://www.visualstudio.com/" target="_blank" rel="noopener noreferrer"&gt;Visual Studio&lt;/a&gt;
, &lt;a href="https://dotnet.microsoft.com/en-us/apps/xamarin" target="_blank" rel="noopener noreferrer"&gt;Xamarin Forms&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="android-studio"&gt;Android Studio&lt;a class="anchor ms-1" href="#android-studio" aria-label="Permalink: Android Studio"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don’t know much about this option so do correct me if I don’t get the details correct.&lt;/p&gt;
&lt;p&gt;Android Studio can be downloaded from Google this allows you to create java code to run directly on an android device. From what I know this is fairly similar experience to Visual Studio but instead of writing your code in C# you use Android Studio and write it directly in java.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.android.com/studio/index.html" target="_blank" rel="noopener noreferrer"&gt;More information&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="cordova"&gt;Cordova&lt;a class="anchor ms-1" href="#cordova" aria-label="Permalink: Cordova"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cordova allows you to use HTML, CSS and javascript to create cross platform apps. I have no idea why I haven’t heard of this technology until today as it sounds very flexible especially if you know a little bit of javascript.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cordova.apache.org/docs/en/latest/guide/overview/" target="_blank" rel="noopener noreferrer"&gt;More information&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;To summarize there are lots of different options available to create an android app. What you choose depends on what you want to build, what language and experience you have and if your app needs to be cross platform.&lt;/p&gt;</description></item><item><title>Tips for Developing Yourself</title><link>https://blog-dev.funkysi1701.com/posts/2018/tips-for-developing-yourself/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 19 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/tips-for-developing-yourself/</guid><category term="Blogging">Blogging</category><category term="Goals">Goals</category><description>&lt;p&gt;For a while I have been mentoring a friend and I thought I might share some top tips I have implemented in my career so far.&lt;/p&gt;
&lt;h2 id="hard-work"&gt;Hard Work&lt;a class="anchor ms-1" href="#hard-work" aria-label="Permalink: Hard Work"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At school I was told: “&lt;em&gt;Only in the dictionary does Success come before Work&lt;/em&gt;“. Yes it is a bit of a corny saying however it has stuck in my head and it’s true. If you want to get anywhere you need to work at it. For many years I just drifted along, but as soon as I knuckled down and worked hard my career started going somewhere.&lt;/p&gt;
&lt;h2 id="write-a-blog"&gt;Write a Blog&lt;a class="anchor ms-1" href="#write-a-blog" aria-label="Permalink: Write a Blog"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Writing is an important skill that you need to work at to improve. If you commit to writing one blog post a week this will help to improve this skill. Even after 150+ blog posts I still feel I need to improve. Not only that it will also help others learn something from you and shows a willingness to contribute to the community. If a Hiring Manager reads your blog he can see some of the stuff you know or care about and may help give you the edge over more experienced candidates.&lt;/p&gt;
&lt;h2 id="soft-skills"&gt;Soft Skills&lt;a class="anchor ms-1" href="#soft-skills" aria-label="Permalink: Soft Skills"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is one I need to work on but you should concentrate on the so called “&lt;em&gt;Soft Skills&lt;/em&gt;“. Soft Skills are the skills you have for dealing with others. Are you good at talking to people? Or good at getting requirements out of business owners? If so you have some soft skills, don’t underestimate the value that these bring to a team and keep developing them.&lt;/p&gt;
&lt;h2 id="build-a-side-project"&gt;Build a Side Project&lt;a class="anchor ms-1" href="#build-a-side-project" aria-label="Permalink: Build a Side Project"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Start building a side project, it doesn’t matter what it is but start building something. I started building a Xamarin app but I have learnt loads of other connected things while doing this, ViewModels, APIs, Build and Deployment processes, Azure Functions. It also gives you ammunition for things to blog about. If you are short of ideas try solving a problem or rebuild something you use.&lt;/p&gt;
&lt;h2 id="use-your-spare-time"&gt;Use your spare time&lt;a class="anchor ms-1" href="#use-your-spare-time" aria-label="Permalink: Use your spare time"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;During the day there are moments you can reclaim for learning stuff. There are lots of &lt;a href="https://www.funkysi1701.com/podcasts" target="_blank" rel="noopener noreferrer"&gt;podcast&lt;/a&gt;
which discuss useful development topics, listen to these while driving to work. Subscribe to &lt;a href="https://www.funkysi1701.com/posts/2018/pluralsight/" target="_blank" rel="noopener noreferrer"&gt;pluralsight&lt;/a&gt;
and listen to this while washing up. Don’t get too concerned with learning everything, however think how much more you are learning than not listening at all.&lt;/p&gt;
&lt;h2 id="im-not-ready"&gt;I’m not ready!&lt;a class="anchor ms-1" href="#im-not-ready" aria-label="Permalink: I’m not ready!"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We are never ready to take that next step, it is so easy to make excuses like I need to learn x, or know y. The only way to know if you are ready is to try and to keep trying. Iterate as you go so you keep improving yourself. If you wait before you start trying you will end up waiting forever. If you start trying now you will make some small progress and have a better idea of what you need to do to achieve your goals.&lt;/p&gt;</description></item><item><title>Heroes</title><link>https://blog-dev.funkysi1701.com/posts/2018/heroes/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Fri, 16 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/heroes/</guid><category term="StephenHawking">StephenHawking</category><category term="Hero">Hero</category><description>&lt;p&gt;&lt;strong&gt;Who was your hero growing up?&lt;/strong&gt; Mine was Stephen Hawking.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Stephen Hawking" src="https://blog-dev.funkysi1701.com/images/2018/Hawking-ZeroG_web-1.jpg" loading="lazy"
width="1024" height="415"
/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is a hero?&lt;/strong&gt; A lot is said in the media about “Heroes”. Often the sportsperson of the hour is described as a hero. I don’t like this definition and I think there is far more to being a hero than that. One definition I saw describes a hero as &lt;em&gt;A person who is admired for their courage, outstanding achievements, or noble qualities.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why Hawking?&lt;/strong&gt; As a kid I thought I was pretty smart (Not really just above average), I liked Star Trek and science so Hawking was a pretty obvious choice. I remember reading all about Hawking and his life fascinated me. A brilliant man was struck down by motor neurone disease in his early twenties, however this did not stop him and he completed his doctorate and became the famous physicist we all know and love.&lt;/p&gt;
&lt;p&gt;My physics career was fairly short lived ending with an undergraduate course at University of York, however I really enjoyed learning the concepts that he described about space and time and was definitely a driving factor for me to learn as much as I did about Physics.&lt;/p&gt;
&lt;p&gt;How heroic is it to be given 2 years to live and then not only survive but to expand our understanding of the universe without being able to speak or move without the aid of technology?&lt;/p&gt;
&lt;p&gt;I can not imagine what it must be like to not be able to communicate without the use of a computer, but this has been Stephen Hawkings world for over 30 years. His computer system has undergone various upgrades over the years however his synthetic computer voice has continued as he identified with it and prefered it.&lt;/p&gt;
&lt;p&gt;Stephen Hawking had an immense intellect, I would probably describe him as one of the cleverest people on the planet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who are your heroes?&lt;/strong&gt; What kind of person is your hero, is it a scientist or engineer? The world contains some very clever people who will inspire and excite young people to strive towards something. I am hopeful that my sons can be inspired even if it’s only a small way by someone like Stephen Hawking.&lt;/p&gt;</description></item><item><title>New version of Pwned Pass</title><link>https://blog-dev.funkysi1701.com/posts/2018/new-version-pwned-pass/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 05 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/new-version-pwned-pass/</guid><category term="Android">Android</category><category term="PwnedPass">PwnedPass</category><category term="App">App</category><media:content medium="image" type="image/png" url="https://blog-dev.funkysi1701.com/images/google/pwned-pass-icon.png"/><description>&lt;p&gt;
&lt;img class="img-fluid" alt="Pwned Pass" src="https://blog-dev.funkysi1701.com/images/google/pwned-pass-icon.png" loading="lazy"
width="506" height="900"
/&gt;
A new version of Pwned Pass is available from Google Play.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago &lt;a href="https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/" target="_blank" rel="noopener noreferrer"&gt;Troy Hunt&lt;/a&gt;
released V2 of Pwned Pass onto his &lt;a href="https://haveibeenpwned.com/" target="_blank" rel="noopener noreferrer"&gt;haveibeenpwned&lt;/a&gt;
website. There are now over half a billion passwords that have appeared in data breaches for you to search.&lt;/p&gt;
&lt;p&gt;This time Troy has included information about how many times a password has appeared in his data. So “password” returns a value of 3,303,003 so is a really, really bad choice of password to use. However the password “windows 10” has only appeared twice so is much better, however I would still recommend avoiding using it.&lt;/p&gt;
&lt;p&gt;One of the great things about the internet is that on the day of release I was tweeting Troy so I could get my android app updated to take advantage of these new features. I even helped him identify an issue with the documentation on his site. He has also kindly add a link to my app onto his website.&lt;/p&gt;
&lt;p&gt;That conversation and link has lead to a massive increase in app downloads. Before I was going steady on about 14 installs, now I have 86 active installs. I am not sure if this will increase anymore but if you are reading this because you downloaded my app, then thank you.&lt;/p&gt;
&lt;p&gt;My app has four main features:&lt;/p&gt;
&lt;p&gt;Password Check – this allows you to search a password and see if it has appeared in a data breach and also the number of times that password has appeared.&lt;/p&gt;
&lt;p&gt;Email Check – this allows you to search your email address and see which data breach it has been involved in.&lt;/p&gt;
&lt;p&gt;List of Data Breaches – this lists the data breaches from haveibeenpwned.com you can also sort by Date Added, Number of accounts and name.&lt;/p&gt;
&lt;p&gt;Calendar of Breaches – this shows a github like chart of what days breaches are added&lt;/p&gt;
&lt;p&gt;If you like my app do let me know. I have received a few ratings on google play it would be great to get a few more. If you want me to add a feature or have ideas of how I could improve it let me know as well.&lt;/p&gt;
&lt;p&gt;To download take a look at &lt;a href="https://play.google.com/store/apps/details?id=pwnedpasswords.pwnedpasswords" target="_blank" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=pwnedpasswords.pwnedpasswords&lt;/a&gt;
&lt;/p&gt;</description></item><item><title>Refactoring if statements</title><link>https://blog-dev.funkysi1701.com/posts/2018/refactoringifstatements/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 26 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/refactoringifstatements/</guid><category term="Design">Design</category><category term="Class">Class</category><category term="Interface">Interface</category><description>&lt;p&gt;The code base I am working on contains a huge if block. By huge I mean 77 if statements one after the other, each if checks to see what page id you are on and loads different content. This is not easy to maintain and I want to refactor it.&lt;/p&gt;
&lt;p&gt;One option would be to replace the if statements with a switch block. However this is just as unmanageable as the huge if block. Lets look at a better option.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Polymorphism&lt;/strong&gt; is where you create a base class and then create sub classes from it. In my case I created an interface IPage with a single method CreateContent.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IPage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; CreatePageContent();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and then create 77 classes for each page which implemented this single method.&lt;/p&gt;
&lt;p&gt;Now comes the fun bit how do I call the correct page class from my original code?&lt;/p&gt;
&lt;p&gt;I created a dictionary than maps page ids to the class names.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; Dictionary&amp;lt;PageIds, Type&amp;gt; PageIdToClass = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Dictionary&amp;lt;PageIds, Type&amp;gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PageIds.HomePage,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt;(HomePage)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PageIds.ContactPage,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt;(ContactPage)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//etc &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the one step I am not 100% happy with as I think it may be possible to remove or simplify this step.&lt;/p&gt;
&lt;p&gt;Now I have a way to map ids to classes I can write a class to do this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyPage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IPage _repo;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; MyPage(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; pageId)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; PageIds p = (PageIds)pageId;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Type t = PageIdToClass[p];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConstructorInfo constructor = t.GetConstructor(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Type[] { });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _repo = (IPage)constructor.Invoke(&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; Create()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; _repo.CreatePageContent();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So in my constructor I take the pageId and pass it to my dictionary to get which subclass to load. I then get its Constructor and invoke it.&lt;/p&gt;
&lt;p&gt;Now I can remove the huge if block and replace it with a single line of code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; page = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; MyPage(pageId);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the face of it this change might look like a lot of work for not much gain as we started off with one file and now we have the original file, an interface, 77 subclasses and the MyPage class. However the original file is a lot more manageable and each sub class can be altered independently of each other.&lt;/p&gt;
&lt;p&gt;This is a big step towards making this code more maintainable, there is always more that can be done but that can wait for another day.&lt;/p&gt;</description></item><item><title>Chrome distrusts SSL Certificates</title><link>https://blog-dev.funkysi1701.com/posts/2018/ssl-distrusts/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 19 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/ssl-distrusts/</guid><category term="Certificates">Certificates</category><category term="SSL">SSL</category><category term="Security">Security</category><category term="DevOps">DevOps</category><description>&lt;p&gt;One of the websites I have been working on has been displaying an error in the console. The error reads as follows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The SSL certificate used to load resources from https://example.com will be distrusted in M70. Once distrusted, users will be prevented from loading these resources. See https://g.co/chrome/symantecpkicerts for more information.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what does this mean? Well let’s start by looking at the &lt;a href="https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html" target="_blank" rel="noopener noreferrer"&gt;link&lt;/a&gt;
provided.&lt;/p&gt;
&lt;p&gt;In January 2017 it was revealed that Certificate Authorities run by Symantec which include Thawte, VeriSign, Equifax, GeoTrust, and RapidSSL had been issuing certificates that did not comply with baseline standards.&lt;/p&gt;
&lt;p&gt;Starting with Chrome 66, Google has decided to remove trust for these certificates. Chrome 66 is due for release around 17th April. My error mentions M70 so what does that refer to?&lt;/p&gt;
&lt;p&gt;Chrome 70 which is due to be released in October 2018 will removed the trust for another batch of Symantec certificates.&lt;/p&gt;
&lt;p&gt;If you are getting one of these errors because you are using a certificate that is going to be distrusted what will your site look like in Chrome 66 or Chrome 70?&lt;/p&gt;
&lt;p&gt;Well Chrome 66 is now in the dev channel so we can give it a try.
&lt;img class="img-fluid" alt="Chrome browser warning that a Symantec SSL certificate is distrusted" src="https://blog-dev.funkysi1701.com/images/2018/tempsnip.png.jpg" loading="lazy"
width="1673" height="1119"
/&gt;
&lt;/p&gt;
&lt;p&gt;Not very nice for your users is it? Now is the time to order a new SSL certificate to avoid this happening to your site.&lt;/p&gt;
&lt;p&gt;I first saw this error a few months ago and have been reading up about it and waiting for Chrome 66 to reach the dev channel so I could test what it did to my site. However now that I have Chrome 66 installed I spotted the intranet for the company I work for is also affected. I do not directly work on the intranet so I notified the security team that they may want to look into this.&lt;/p&gt;
&lt;p&gt;Unfortunately the response I received has been that Google needs to fix this before Chrome 66 is released. I am not criticising my employer or the security team, however this isn’t something Google can just “ &lt;strong&gt;fix&lt;/strong&gt; “.&lt;/p&gt;
&lt;p&gt;The certificates issued were issued by a CA that had issues so in order to maintain the trustworthiness of all certificates Google had little choice but to distrust them. Google and security experts need to be making more of a fuss about this and I am joining in on making a fuss by writing this blog. &lt;a href="https://scotthelme.co.uk/are-you-ready-for-the-symantec-distrust/" target="_blank" rel="noopener noreferrer"&gt;Scott Helme&lt;/a&gt;
estimates that there are about 7000 websites which may be affected by the M66 and M70 distrusts.&lt;/p&gt;</description></item><item><title>Content Security Policies</title><link>https://blog-dev.funkysi1701.com/posts/2018/content-security-policies/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 12 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/content-security-policies/</guid><category term="CSP">CSP</category><category term="ReportURI">ReportURI</category><category term="Security">Security</category><description>&lt;p&gt;A content Security Policy or CSP is a HTTP response header that defines what sources of content can be loaded on a web page. It is a way to combat Cross Site Scripting (XSS) attacks.&lt;/p&gt;
&lt;h2 id="what-is-a-xss-attack-then"&gt;What is a XSS attack then?&lt;a class="anchor ms-1" href="#what-is-a-xss-attack-then" aria-label="Permalink: What is a XSS attack then?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you load a webpage it also loads various other resources like images, some css style sheets, various javascript files that you want to run and probably many other things.&lt;/p&gt;
&lt;p&gt;How do you know that you can trust all of these things? If you created them and they live under you control then the answer is probably yes. However these days you will probably want to use resources from across the internet, like youtube videos, google analytics, disqus comments, jquery libraries from a cdn etc and you can’t be sure exactly what they are doing.&lt;/p&gt;
&lt;p&gt;Imagine you had a page which you could add any text into a form which would then be displayed. A malicious user could add evil javascript or get the browser to load evil code from anywhere on the internet.&lt;/p&gt;
&lt;h2 id="csp-to-the-rescue"&gt;CSP to the rescue!&lt;a class="anchor ms-1" href="#csp-to-the-rescue" aria-label="Permalink: CSP to the rescue!"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A CSP allows the browser to only load from sources that you specify. You could specify that resources from your own site will load but the evil script will not.&lt;/p&gt;
&lt;p&gt;Let’s look at some examples&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Content-Security-Policy: script-src &amp;#39;self&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags to only load from the current webhost. script-src is not the only keyword you can use, let’s look at some of the others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;script-src&lt;/strong&gt; – control what &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags will load&lt;br&gt;
&lt;strong&gt;style-src&lt;/strong&gt; – control what css will load&lt;br&gt;
&lt;strong&gt;img-src&lt;/strong&gt; – control what images will load&lt;br&gt;
&lt;strong&gt;frame-src&lt;/strong&gt; – control what frames will load&lt;br&gt;
&lt;strong&gt;font-src&lt;/strong&gt; – control what fonts will load&lt;br&gt;
&lt;strong&gt;object-src&lt;/strong&gt; – control what object tags will load&lt;br&gt;
&lt;strong&gt;connect-src&lt;/strong&gt; – control what resources a script can connect to&lt;br&gt;
&lt;strong&gt;media-src&lt;/strong&gt; – controls what media (audio/video) will load&lt;br&gt;
&lt;strong&gt;default-src&lt;/strong&gt; – if no specific rule exists then the default directive will run&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Content-Security-Policy: default-src https
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows any content to be loaded from any site as long as it comes from a secure (https) site&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Content-Security-Policy: default-src https://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows any content to be loaded from &lt;a href="https://example.com" target="_blank" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;
only.&lt;/p&gt;
&lt;h2 id="how-do-i-use-this-on-my-site"&gt;How do I use this on my site?&lt;a class="anchor ms-1" href="#how-do-i-use-this-on-my-site" aria-label="Permalink: How do I use this on my site?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have added CSPs into my web.config which works great for my .Net Framework code.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; &amp;lt;system.webServer&amp;gt; &amp;lt;httpProtocol&amp;gt; &amp;lt;customHeaders&amp;gt; &amp;lt;add name=&amp;#34;Content-Security-Policy&amp;#34; value=&amp;#34;default-src https://example.com&amp;#34; /&amp;gt; &amp;lt;/customHeaders&amp;gt; &amp;lt;/httpProtocol&amp;gt; &amp;lt;/system.webServer&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For .net core it is a bit more complex as you don’t tend to use web.config files, however check out Anthony Chu’s &lt;a href="https://anthonychu.ca/post/aspnet-core-csp/" target="_blank" rel="noopener noreferrer"&gt;post&lt;/a&gt;
, which has a solution to that problem.&lt;/p&gt;
&lt;h2 id="report-only"&gt;Report Only&lt;a class="anchor ms-1" href="#report-only" aria-label="Permalink: Report Only"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One last thing about CSPs to mention is the Report Only flag.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Content-Security-Policy-Report-Only
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This does the same as the above but doesn’t enforce anything, so you can fix any problems before you break anything.&lt;/p&gt;
&lt;p&gt;To view your issues just look in the developer tools in your favourite browser. Or you can configure all your reports to be collated in one place with a report-uri directive.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Content-Security-Policy: default-src https://example.com; report-uri https://example.report-uri.com/r/d/csp/reportOnly;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Scott Helme and Troy Hunt have a site called &lt;a href="https://report-uri.com/" target="_blank" rel="noopener noreferrer"&gt;report-uri&lt;/a&gt;
which offer a service for collating and viewing all your CSP violations so check it out if you want to know more about CSPs.&lt;/p&gt;</description></item><item><title>Pluralsight</title><link>https://blog-dev.funkysi1701.com/posts/2018/pluralsight/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 05 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/pluralsight/</guid><category term="Learning">Learning</category><category term="Training">Training</category><category term="Pluralsight">Pluralsight</category><category term="C-Sharp">C-Sharp</category><description>&lt;p&gt;Earlier this year I signed up for pluralsight. If you want to sign up to pluralsight as well use this link &lt;a href="https://referral.pluralsight.com/mQd8BJ4" target="_blank" rel="noopener noreferrer"&gt;https://referral.pluralsight.com/mQd8BJ4&lt;/a&gt;
to get money off.&lt;/p&gt;
&lt;p&gt;Pluralsight is a website that sells training videos on a wide variety of technical topics. You sign up for a monthly or annual subscription and you can watch over 6000 courses whenever and where ever you like.&lt;/p&gt;
&lt;p&gt;I am not a big fan of videos as if I am sat in front of a screen I would rather be building something, however I do spend a lot of time listening to podcasts. So I have decided to convert this time to listening to pluralsight videos.&lt;/p&gt;
&lt;p&gt;If we assume that by not seeing the visual portion of the videos you lose out on 75% of the learning (This is just a guesstimate I am not sure what the exact figure is or how you would calculate it). However this is still 25% more learning than if I hadn’t signed up at all.&lt;/p&gt;
&lt;p&gt;Since I signed up I have listened to over 27 hours of technical videos. These have covered topics like C#, Security, Xamarin, MVVM, Interfaces, Getting Involved and Clean architecture. The number one thing I have learnt is that there is a lot that I still don’t understand.&lt;/p&gt;
&lt;p&gt;That said I would like to think that since starting to listen to pluralsight concepts have gone from being unknown unknowns (I don’t know about them and I don’t understand them) to known unknowns (I know about them but don’t yet fully understand them)&lt;/p&gt;
&lt;p&gt;To keep track of your learning pluralsight has some tests which you can complete. I am particularly proud of my score on the Azure test which ranks me as an expert.&lt;/p&gt;
&lt;p&gt;Why not check out what you can learn from pluralsight?&lt;/p&gt;</description></item><item><title>Flexible architecture and interfaces</title><link>https://blog-dev.funkysi1701.com/posts/2018/flexible-architecture/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 29 Jan 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/flexible-architecture/</guid><category term="Architecture">Architecture</category><category term="Azure">Azure</category><description>&lt;p&gt;I have blogged a few times about &lt;a href="https://www.funkysi1701.com/posts/2017/interfaces/" target="_blank" rel="noopener noreferrer"&gt;interfaces&lt;/a&gt;
, and how useful they are for producing good quality maintainable code. Let’s look at a problem and the solution I came up with which I am quite proud of.&lt;/p&gt;
&lt;p&gt;As previously mentioned I am in the process of moving &lt;a href="https://www.funkysi1701.com/posts/2018/moving-blobs-cloud-suppliers/" target="_blank" rel="noopener noreferrer"&gt;images&lt;/a&gt;
from AWS to Azure blob storage. Now that the actual files themselves have been moved I need to change the code that references them.&lt;/p&gt;
&lt;p&gt;Now I could find all the code that uses the AWS API and replace it with the Azure API but I am not very good at predicting the future, we may stay on Azure for a while, we may move to AWS or Google Cloud, or we may want to go back to files sitting on a server.&lt;/p&gt;
&lt;p&gt;Lets try and code a solution that is as flexible as possible. As you have probably guessed I am going to create an interface.&lt;/p&gt;
&lt;p&gt;At first I thought about creating an interface called &lt;strong&gt;ICloudStorage&lt;/strong&gt; , however this isn’t flexible enough as what happens if we go back to sticking files on a server so instead I created &lt;strong&gt;IStorage&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I created three classes that implemented IStorage, &lt;strong&gt;AWSStorage&lt;/strong&gt; , &lt;strong&gt;AzureStorage&lt;/strong&gt; and mostly for testing at the moment &lt;strong&gt;FileStorage&lt;/strong&gt;. I then created a class Storage that would call these three classes. Initially I created it like this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; IStorage _repo;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; Storage(IStorage repo)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _repo = repo;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However this would require I call it like Storage(new AzureStorage()) and I would need to know everywhere in my code which implementation I want to use. This isn’t too bad as when we change from AWS to Azure we would need to do a find and replace throughout the code and replace all AWSStorage and make them AzureStorage.&lt;/p&gt;
&lt;p&gt;However we can do better than that.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; IStorage _repo;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; Storage()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Type obj = Type.GetType(ConfigurationManager.AppSettings[&lt;span style="color:#e6db74"&gt;&amp;#34;DefaultStorageRepository&amp;#34;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ConstructorInfo constructor = obj.GetConstructor(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Type[] { });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _repo = (IStorage)constructor.Invoke(&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code will read from the web.config which implementation to use and that will decide which class to call. This means that to change from AWS to Azure we do not need to redeploy any code, all we need to do is change the web.config.&lt;/p&gt;
&lt;p&gt;Let’s look at the three lines and see if we can understand what is happening.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Type.GetType()&lt;/strong&gt; looks straight forward and gets the type from the web.config&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;obj.GetConstructor()&lt;/strong&gt; This gets the constructor for the type we have just found.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;constructor.Invoke&lt;/strong&gt; This then invokes the constructor and it then gets cast to the interface so can be used by the _repo variable.&lt;/p&gt;
&lt;p&gt;This is all fairly simple and makes sense, however it has produced some very flexible code and allows the code to be extended without recompiling.&lt;/p&gt;
&lt;p&gt;Let’s look at a hypothetical example. We want to add support for Google Cloud Storage. All we need to do is create a class library which implements the IStorage interface, place the compiled binary in the website and update the web.config to reference it. I haven’t tried this hypothetical example so it might be more complex than I think but in theory it should work.&lt;/p&gt;
&lt;p&gt;I am pretty excited at how flexible this code can be, hopefully I will use code like this more often now I understand it.&lt;/p&gt;</description></item><item><title>Moving files into blob storage</title><link>https://blog-dev.funkysi1701.com/posts/2018/moving-blobs-cloud-suppliers/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 22 Jan 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/moving-blobs-cloud-suppliers/</guid><category term="DevOps">DevOps</category><category term="Azure">Azure</category><description>&lt;p&gt;We are in the process of moving our companies websites onto the Azure platform. One of the challenges was to move image files out of the website project into blob storage. This week I have moved 150,000 of them.&lt;/p&gt;
&lt;p&gt;One thing I keep banging on about is that your source code should not contain data. If it does every time you do a deployment you need to consider where these images are located and ensure you don’t overwrite or loose any. It also goes without saying that deployments of a few Mb are a lot quicker than deployments of 100s of Mb.&lt;/p&gt;
&lt;p&gt;Azure blob storage also gives you advantages like distributing storage across multiple datacenters which would be impossible with traditional files on a server.&lt;/p&gt;
&lt;p&gt;So now that we have established that this is a good idea lets look at how we could move large amounts of data. In my case all the filenames are stored in a SQL database so the plan of action was to simply loop through the files in the database, download from current storage (either locally or other cloud storage), upload to Azure and tidy up afterwards. Due to the number of images I am going to update the database and mark when a file has been processed so I can do the move over several days.&lt;/p&gt;
&lt;p&gt;This is my code&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; source = &lt;span style="color:#e6db74"&gt;&amp;#34;https://example.com/images/&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; tmp = Server.MapPath(&lt;span style="color:#e6db74"&gt;&amp;#34;~/tmp/&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (!Directory.Exists(tmp))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Directory.CreateDirectory(tmp);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; fixturePhotos = db.Images.Where(x =&amp;gt; x.Moved == &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; || x.Moved == &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;).Take(id);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;foreach&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; photo &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; fixturePhotos)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; path = getFilePath(photo.FileName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (!Directory.Exists(Server.MapPath(&lt;span style="color:#e6db74"&gt;&amp;#34;~/tmp/&amp;#34;&lt;/span&gt; + path)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Directory.CreateDirectory(Server.MapPath(&lt;span style="color:#e6db74"&gt;&amp;#34;~/tmp/&amp;#34;&lt;/span&gt; + path));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WebClient WebClient = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; WebClient();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; WebClient.DownloadFile(source + photo.FileName, tmp + photo.FileName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FileUploader f = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; FileUploader(tmp + photo.FileName, photo.FileName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.IO.File.Delete(tmp + photo.FileName);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; photo.Moved = &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; photo.Moved = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db.SaveChanges();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (Directory.Exists(tmp))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Directory.Delete(tmp, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First of all I create a tmp folder in the root of my website if it doesn’t exist to store my images temporarily.&lt;/p&gt;
&lt;p&gt;I then use an entity framework model to query the database that haven’t been moved, and I use the take() method to limit how many results I process. (I have been passing in 1000 at a time)&lt;/p&gt;
&lt;p&gt;I then use a foreach loop over all these files to perform the following actions.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create additional subfolders if the filename variable stored in the database isn’t actually a filename but a filepath, note you will have to split filename and filepath which I haven’t included code for here.&lt;/li&gt;
&lt;li&gt;Download file from the original url and save into the temporary folder&lt;/li&gt;
&lt;li&gt;Upload to Azure&lt;/li&gt;
&lt;li&gt;Delete temporary file&lt;/li&gt;
&lt;li&gt;Update database giving a success or fail&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once the foreach is finished I commit the database changes and delete the temporary folder. I am sure there must be other ways to do this transfer but this was quick and easy to setup and now I have a copy of all the files in Azure storage so I can test out other issues with my website.&lt;/p&gt;
&lt;p&gt;One last tip about how to schedule this code. I called the above code from a MVC controller and then wrote a Azure Function to call this code on a schedule.&lt;/p&gt;</description></item><item><title>Website UI Testing</title><link>https://blog-dev.funkysi1701.com/posts/2018/website-ui-testing/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 15 Jan 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/website-ui-testing/</guid><category term="Testing">Testing</category><category term="Website">Website</category><category term="UI">UI</category><description>&lt;p&gt;Last week I looked at testing the &lt;a href="https://dev.to/funkysi1701/mobile-app-ui-testing-jgg-temp-slug-9433902" target="_blank" rel="noopener noreferrer"&gt;UI of mobile apps&lt;/a&gt;
, this week lets look at how we could do a similar thing for websites.&lt;/p&gt;
&lt;p&gt;Testing the user interface is not an excuse for a lack of &lt;a href="https://dev.to/funkysi1701/writing-your-first-test-53gi-temp-slug-2645725" target="_blank" rel="noopener noreferrer"&gt;unit tests&lt;/a&gt;
. Testing the user interface takes longer so for keep creating your small unit tests that can be run after ever build. That said lets look at how you create a UI test.&lt;/p&gt;
&lt;p&gt;Create a Unit Test project as normal. Now install the following nuget packages&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Selenium.WebDriver.ChromeDriverSelenium.WebDriverSelenium.WebDriver.PhantomJS.Xplatform
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I am going to be using Selenium to achieve my website testing and I am going to concentrate on the Chrome browser. However packages exist for other browsers so have a look at the following and I expect there are others as well.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Selenium.WebDriver.IEDriverSelenium.Firefox.WebDriver
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://seleniumhq.org/" target="_blank" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;
started life as a plugin for Firefox to help create automated tests, however the latest version of Firefox is not compatible with the plugin as I write this. I have not had to install any plugins or extensions to my browsers to achieve my testing.&lt;/p&gt;
&lt;p&gt;Enough talk lets write a test. First we create two instance variables to store the baseURL and the driver for the browser you are using.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; baseURL = &lt;span style="color:#e6db74"&gt;&amp;#34;https://www.example.com/&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; RemoteWebDriver driver;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we need to set things up for the test to run. This creates an instance of the chrome driver, maximizes the window and sets it to wait 30 seconds before timing out.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[TestInitialize()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; MyTestInitialize()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ChromeDriver();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver.Manage().Window.Maximize();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now comes the actual test. We navigate to a URL and then compare the title of the page loaded with a know value with a Assert statement like you would find in a unit test.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[TestMethod]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; CheckBrowserTitle()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver.Navigate().GoToUrl(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.baseURL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Assert.AreEqual(&lt;span style="color:#e6db74"&gt;&amp;#34;Home Page&amp;#34;&lt;/span&gt;, driver.Title);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally we need to tidy up after ourselves.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[TestCleanup()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; MyTestCleanup()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver.Quit();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you are used to writing tests you will know that the are usually constructed in three sections Arrange, Act and Assert. The Arrange is done in the initialize method, which makes the actual test much simpler, the first line does the Act and the last line does the Assert.&lt;/p&gt;
&lt;p&gt;Now we have written a simple test lets look at something more complex.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver.FindElementByLinkTest(&lt;span style="color:#e6db74"&gt;&amp;#34;click&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This finds any Link on the page which is click. Be careful as the string need to be exactly what appears on screen it may well be easier to specify by id or class or something that doesn’t change as often. By adding .click() on the end of this command Selenium will click on the link and you can navigate to a new page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What about submitting form data?&lt;/strong&gt; Well you can find the element you want to fill in and add .SendKeys(&amp;ldquo;example text&amp;rdquo;) or .Submit() and this will fill in and submit form data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What about a screenshot?&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Screenshot ss = driver.GetScreenshot();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ss.SaveAsFile(&lt;span style="color:#e6db74"&gt;&amp;#34;test.jpg&amp;#34;&lt;/span&gt;,System.Drawing.Imaging.ImageFormat.Jpeg);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have only just started playing around with web UI tests but you can see there is a fair bit you can do.&lt;/p&gt;</description></item><item><title>Mobile App UI Testing</title><link>https://blog-dev.funkysi1701.com/posts/2018/mobile-app-ui-testing/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 08 Jan 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/mobile-app-ui-testing/</guid><category term="Android">Android</category><category term="Azure">Azure</category><category term="App">App</category><media:content medium="image" type="image/png" url="https://blog-dev.funkysi1701.com/images/2018/01/01-newproject-vs.png"/><description>&lt;p&gt;Since I started creating an android app I have been writing simple UI tests.&lt;/p&gt;
&lt;p&gt;I have been taking advantage of the Visual Studio App Center which allows you to test against hundreds of different devices in the &lt;strong&gt;Test Cloud&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Xamarin UI tests" src="https://blog-dev.funkysi1701.com/images/2018/01/01-newproject-vs.png" loading="lazy"
width="1371" height="834"
/&gt;
In order to write a UI test create a UI Test App, this makes use of the nuget package Xamarin UI Test. By default you will now have a test called AppLaunches which will take a screenshot of you app after it starts.&lt;/p&gt;
&lt;p&gt;You can now run this test against any device from Visual Studio assuming you have it physically plugged into your machine. However, how do you run against the Test Cloud?&lt;/p&gt;
&lt;p&gt;To run against the Test Cloud you need to first install node.js. Now you can install the appcenter cli with the following command.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;**npm** install -g appcenter-cli
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To run the tests in the Test Cloud run the following command&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;**appcenter** test run uitest --app &amp;#34;&amp;lt;username&amp;gt;/&amp;lt;appname&amp;gt;&amp;#34; --devices &amp;#34;&amp;lt;username&amp;gt;/&amp;lt;deviceset&amp;gt;&amp;#34; --app-path _pathToFile.apk_ --test-series &amp;#34;master&amp;#34; --locale &amp;#34;en_US&amp;#34; --build-dir _pathToUITestBuildDir_
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;where &lt;username&gt; is your appcenter username, is the name of your app in appcenter and is the group of apps you have created in app center to test against.&lt;/p&gt;
&lt;p&gt;Look at device sets in the test section of the appcenter and click the new device set button. You can then search for any device you like and add it to a set, as I write this there are 244 devices you can test against.&lt;/p&gt;
&lt;p&gt;It is currently not possible within app center to run tests against a new build, however if you build your app in VSTS as well you can create build or release step that runs it. As the Visual Studio app center is still under development I wouldn’t be surprised if it is added at some point.&lt;/p&gt;
&lt;p&gt;In VSTS look for Mobile Center Test in the definitions and you can specify the same variables as specified in the command line above.&lt;/p&gt;
&lt;p&gt;Now how do you actually write a useful UI test? I mentioned above you get a default test which contains the following code, this takes a screenshot of your app. However you don’t have to include this when using the Test Cloud as screenshots are included for free.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;app.Screenshot(&amp;#34;First screen.&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lets look at what else is included in app&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;app.Repl();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This starts an interactive REPL (Read-Eval-Print-Loop) which lets you explore what is on screen in your app and pauses execution. I don’t include this in my tests, however I do make use of it to explore what is on screen and what tests I might make use of.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;app.Tap(c =&amp;gt; c.Marked(&amp;#34;Button&amp;#34;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This taps an element on screen called Button. There is also a method called TapCoordinates which would allow you to click anywhere you like.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;app.WaitForElement(c =&amp;gt; c.Marked(&amp;#34;View&amp;#34;));
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After clicking a button you are probably going to want to wait for the app to load extra data or a new screen. The WaitForElement waits for an element to appear on screen. There are also methods that wait a period of time or wait until an element no longer exists.&lt;/p&gt;
&lt;p&gt;These are the main methods I have used so far, however there is an extensive list including methods for scrolling, swiping, pinching and adjusting the volume buttons. So you should be able to test all manner of app functionality and if you make use of the Test Clouds will know which devices are causing problems.&lt;/p&gt;</description></item><item><title>Lets see what 2018 can do!</title><link>https://blog-dev.funkysi1701.com/posts/2018/lets-see-2018-can/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 01 Jan 2018 00:00:00 +0000</pubDate><guid>https://blog-dev.funkysi1701.com/posts/2018/lets-see-2018-can/</guid><category term="Career">Career</category><category term="Family">Family</category><category term="Marriage">Marriage</category><category term="Goals">Goals</category><description>&lt;p&gt;It is 2018 so it must be time to think about what my plans and goals are for the new year.&lt;/p&gt;
&lt;h2 id="buy-a-house"&gt;Buy a house&lt;a class="anchor ms-1" href="#buy-a-house" aria-label="Permalink: Buy a house"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="House" src="https://blog-dev.funkysi1701.com/images/2018/LEGO-Classic-10703-Creative-Building-Box-Yellow-House.jpg" loading="lazy"
width="720" height="720"
/&gt;
&lt;/p&gt;
&lt;p&gt;This a huge goal for me. For many years I was content with renting and thought owning my own home wasn’t for me, but then I went and started a family and my career started going in the right direction and my thoughts about this have changed.&lt;/p&gt;
&lt;p&gt;It is going to take a lot of work to make this goal happen in 2018. First I need to save enough money for the deposit, which is far from easy with a wife and two children. Second I need to get our current place sorted ready to physically move which again won’t be easy. Third I need to make a decision which will affect where I live for the next 25 years. At the moment I am torn between the size of property and its physical location, I need to balance both of these and meet the requirements from the rest of the family.&lt;/p&gt;
&lt;p&gt;I do think this is an achievable goal so wish me luck.&lt;/p&gt;
&lt;h2 id="progress-in-my-career"&gt;Progress in my career&lt;a class="anchor ms-1" href="#progress-in-my-career" aria-label="Permalink: Progress in my career"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I need to be careful how I phrase this in case past, current or future employers are reading. I have been working hard at my current role for over a year and I am starting to wonder what is next for me. I am not entirely sure what form this is going to take yet, I have a few ideas on the go and hopefully I can reveal more soon.&lt;/p&gt;
&lt;p&gt;Another one that is very achievable, as long as I have it in the back of my mind as the year goes on progress should be made.&lt;/p&gt;
&lt;h2 id="see-more-of-family"&gt;See more of family&lt;a class="anchor ms-1" href="#see-more-of-family" aria-label="Permalink: See more of family"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I recently missed a family celebration due to the expansion of my own family and it reminded me that there are aunts, uncles and cousins that I haven’t seen in years and it would be nice to reconnect. Also as my own boys get older and are learning to interact it would be great if they could get to know my own family better.&lt;/p&gt;
&lt;p&gt;I don’t have a clear idea how to achieve this one as it takes two but I am going to make more of an effort.&lt;/p&gt;
&lt;h2 id="celebrate-5-years-of-marriage"&gt;Celebrate 5 years of marriage&lt;a class="anchor ms-1" href="#celebrate-5-years-of-marriage" aria-label="Permalink: Celebrate 5 years of marriage"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Wow how has it been five years since we got married? At some point in 2018 I will take time out from the usual and spend it with the wife away from the boys. I won’t give away more details as I want that to be a surprise.&lt;/p&gt;
&lt;h2 id="celebrate-the-birth-of-my-two-sons"&gt;Celebrate the birth of my two sons&lt;a class="anchor ms-1" href="#celebrate-the-birth-of-my-two-sons" aria-label="Permalink: Celebrate the birth of my two sons"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Celebrate James and Edward" src="https://blog-dev.funkysi1701.com/images/2018/james5.jpg" loading="lazy"
width="1080" height="810"
/&gt;
&lt;/p&gt;
&lt;p&gt;I don’t want to get my boys christened as I would like them to make up their own minds when they are old enough, however I do want to celebrate all that they are with a thanksgiving service. Not sure when we are going to sort this, however it is my hope that it will be soon.&lt;/p&gt;
&lt;h2 id="family-holiday"&gt;Family holiday&lt;a class="anchor ms-1" href="#family-holiday" aria-label="Permalink: Family holiday"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Not much of a goal but in the summer I will take time out to spend a week away with the family. In previous years we have done scotland, wales and northumberland. This year I am thinking of somewhere not too far away as Edward is still small, but maybe near where I grew up.&lt;/p&gt;
&lt;h2 id="lightning-talk"&gt;Lightning Talk&lt;a class="anchor ms-1" href="#lightning-talk" aria-label="Permalink: Lightning Talk"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A lightning talk is a very short talk or presentation given at a conference or user group. Friends of mine are having lots of success talking about what they know about and I think it might be time for me to have a go. I am not a natural public speaker so this is a step out of my comfort zone, however I am going to start small and see what happens. At the moment I don’t know what my subject or topic is going to be, my suspicion is that it will be devops related as that interest me more but watch this space.&lt;/p&gt;</description></item></channel></rss>