Archive

Tag Archives: .net

This post describes a complete method for storing settings in Teamcity to avoid any committing them to Github. Settings will be merged into a separate settings file, referenced from web.config, both during Teamcity builds AND, through a Powershell script, also for developing locally.

Don’t store your passwords, keys, connectionstrings etc. in public

By now, everyone should be aware that it is a terrible idea to store secrets in cloud services, such as Github etc.. As descibed by many articles, a simple search on Github, reveals many secrets that should not be available publicly. And you never know when your private repo might be made public or when a colleague makes a mistake and pushes your private RSA key in a web.config in your code.

Find a private place for storage

You need to find a private place, preferable hosted on-site, behind thick firewalls and layers of security, to store your secrets. We were already using Teamcity to build, test and deploy a .net framework solution. So we want to utilize this to store our secret settings and merge them into the config during the build process. Teamcity also has a REST API that makes it possible to fetch the settings to use outside Teamcity, which we will need.

A solution for both Teamcity builds and local development

We need the settings to be available both during the Teamcity build for merging into the settings file, but also locally where we need to run the code during development. And during local development we want to be able to test out settings for different environments also.

Locally we typically build the code through Visual Studio, which through nugets such as SlowCheetah, has support for merging configs from different environments on build. But there are a couple of issues, such as the configs needs to be committed to Github, which we don’t want, and for web projects, such as mine, merging only happens on deploy or package, not on build. So we need a different approach.

Using the ‘file’ reference in appsettings

For developing locally we need to remember that we cannot store the settings in web.config, as this file is checked into Github. So instead we are making use of the “file” reference feature in .net config files. This enables us to store the secret settings in a different file, and NOT check that file into Github. Note that the ‘file’ reference differs from the ‘configsource’ reference as described here. This is important, because when using the ‘configsource’ reference, ALL of your settings must be in the referenced file, which is not the case with the ‘file’ reference. We only want to store secret settings in the referenced file, to not make life too difficult for developers.

Using Powershell to fetch settings and creating the settings file for local development

We will create a powershell script that takes an environment argument, and based on that, calls the Teamcity REST API, to fetch the settings. Then the script will create the secret settings file, referenced from the solution web.config. Every developer can then use that Powershell script to create settings for whatever environment he needs to test.

Using Teamcity Powershell buildstep to creating the settings file for Teamcity build

For the Teamcity build process, we will create a Powershellscript to be run in a Teamcity build step. This script will take the settings a environment parameters from teamcity and create the secret settings file so it is available for deployment with the rest of the build code.

The finished solution

Here is how I implemented the solution.

Teamcity configuration

We need to do 2 things in Teamcity.

1: Add the secret settings

Navigate to your build confguration and add your secret settings as ‘Configuration Parameters’. I am are prefixing the settings with “SecretAppSetting”, for later use.

Teamcity Parameters

Add your secret settings as Configuration Parameters

2: Setup a build step to create the settings file

Next, add a build step to run the Powershell script, you will create for this purpose below. Note that I am adding the Teamcity parameter “teamcity.build.checkoutDir” which I will need later in the script, to determine where to save the settings file.

Teamcity Buildstep

Create a buildstep to run a Powershell script

Powershell script for Teamcity

Next I create the Powershell script to run in Teamcity to create the secret settings file. Note that the “Param” section in the first line, takes the arguments the we passed in the Teamcity buildstep, including the path for where Teamcity has checked out the files from Github. Using this information the scripts creates the settings file on disk, so that it will be available for the building and packaging in a later buildstep.

Param($checkoutDir,$SecretSetting1,$SecretSetting2)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

Function CreateAppSetting {
  param([string]$key,[string]$value )
    $addElement = $doc.CreateElement("add");
    $addElement.SetAttribute("key", $key);
    $addElement.SetAttribute("value", $value);
    $doc.SelectSingleNode("//appSettings").AppendChild($addElement);        
}

$secretAppSettingsConfig = $checkoutDir + "\src\SecretAppSettings.config"
# Create the secret settings file
"<appSettings/>" | Out-File $secretAppSettingsConfig

$doc = [Xml](Get-Content $secretAppSettingsConfig)

CreateAppSetting 'MySecretSettingName1' $SecretSetting1
CreateAppSetting 'MySecretSettingName2' $SecretSetting2

$doc.Save($secretAppSettingsConfig)

Powershell script for developing locally

Next we need to create a different Powershell script to use locally on the developers computers to create local settings for development.

There is a couple of things to note. The line “$ParentFolder = Split-Path -Path $PSScriptRoot -Parent” is there to find out where to generate the settings file. This is a way to do that, which works in both Powershell editors and commandline (as opposed to dotting your way throughm that does note work the same in all places).

My Teamcity server is login protected, so there needs to be a “httpAuth” in the url and note that Teamcity is case-sensitive toward that argument… (that took some time to figure out!).

The line “$teamcityCredentials = Get-Credential -Message “Enter your TEAMCITY credentials (not your AD login)” prompts the user for credentials with a windows box that masks the input, which is better than writing it in clear text in a commandline.

And in the end, the scripts finds all Teamcity settings that prefixed with “SecretAppSetting.” and adds them as app settings.

So the idea is that the developers calls the Powershell script with an environment argument to generate settings for that environment.

Param($buildconfigurationName)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# Find the path where the script is executed to figure out where to generate the settings file
$ParentFolder = Split-Path -Path $PSScriptRoot -Parent
$secretAppSettingsConfig = $ParentFolder + "\SecretAppSettings.config"

switch($buildconfigurationName)
{
    "debug" 
    {
        Write-Host "debug" -ForegroundColor "Yellow"
        $url = 'https://teamcityServer/httpAuth/app/rest/buildTypes/id:DebugStoresSettingsForLocalBuild/parameters'
        Break
    }
    "test" 
    {
        Write-Host "test" -ForegroundColor "Yellow"
        $url = 'https://teamcityServer/httpAuth/app/rest/buildTypes/id:BuildAndDeployTestBranch/parameters'
        Break
    }
    "prod" 
    {
        Write-Host "prod" -ForegroundColor "Yellow"
        $url = 'https://teamcityServer/httpAuth/app/rest/buildTypes/id:BuildProd/parameters'
        Break
    }
    default 
    {
        Write-Host "Invalid or no environment in args. Usage: CreateLocalSettings <environment>" -ForegroundColor "Red"
        Write-Host "Valid environments: debug, test, vendor, preprod, prod" -ForegroundColor "Red"
        Break Script
    }
}

Write-Host "Enter your TEAMCITY login (not your AD login)..." -ForegroundColor "Yellow"
$teamcityCredentials = Get-Credential -Message "Enter your TEAMCITY credentials (not your AD login)"

Write-Host "Calling teamcity to get settings..."
try
{
    $response = Invoke-RestMethod -Method GET -Credential $teamcityCredentials -Uri $url
}
catch
{
   Write-Host $_ -fore green
   echo "Check teamcity connection or your credentials"
   Break Script
}

# clean out old values
"<appSettings/>" | Out-File $secretAppSettingsConfig

# read the cleaned xml doc
$doc = [Xml](Get-Content $secretAppSettingsConfig)

[bool]$settingsFound = $false;

echo "Setting values..."
# This loop finds all setting prefixed with "SecretAppSetting." and adds them as app settings
foreach ($setting in $response.properties.ChildNodes) {
    if($setting.name -like "SecretAppSetting.*"){        
        $settingName = ($setting.name).Remove(0,17);
        Write-Host "Found setting:" $settingName;
        $addElement = $doc.CreateElement("add");
        $addElement.SetAttribute("key", $settingName);
        $addElement.SetAttribute("value", $setting.value);
        $temp = $doc.SelectSingleNode("//appSettings").AppendChild($addElement);        
        $settingsFound = $true;
    }
 }

if($settingsFound)
{
    Write-Host "saving file at:" $secretAppSettingsConfig -ForegroundColor "Green"
    $doc.Save($secretAppSettingsConfig)
    Write-Host "Done!" -ForegroundColor "Green"
}
else
{
    Write-Host "No settings found!" -ForegroundColor "Red"
}

Changes in the .net solution

I need to make sure that the secret settings file is included in the solution as “content” so  that it is included in the packaging a deployment in Teamcity, as I am using a Visuai Studio buildstep in Teamcity. However it should NEVER be comitted to Github (More on that below).

Include Secret Settings file

Include Secret Settings file

Then I need to reference the file in web.config

Reference secret settings file

Reference secret settings file

Changes in Git/Github

Lastly, I need to make sure that the secret settings file is added to the .gitignore file, so that the file is never added to the Github repository.

Change passwords

If you already have had your connectionstrings, keys or any other secret setting added to a web.config or any other file in your Git repo, you need to remove all traces of it or change your passwords/keys etc.

Note that it is the nature of Git to keep all old commits so it is NOT a trivial task to get rid of all the old commits. It is easier to change your passwords for fresh ones.

Advertisements

It can be tricky to merge images and keep a transparent background, on the fly in C#. I compiled this small How To on the subject.

Here is how I did it:

What you do is create a new image with a transparent background and then paint the existing images on to the new one.

I start out with 2 images and I want the green one to be painted over the yellow one:

Top image

Top image

Bottom image

Bottom image

Here is the code to do it:

private WebImage GenerateImage(Image backImage, Image frontImage)
    {
      int targetHeight = 88; //height and width of the finished image
      int targetWidth = 96;

      //be sure to use a pixelformat that supports transparency
      using (var bitmap = new Bitmap(targetWidth, targetHeight,
              PixelFormat.Format32bppArgb))
      {
        using (var canvas = Graphics.FromImage(bitmap))
        {
          //this ensures that the backgroundcolor is transparent
          canvas.Clear(Color.Transparent);

          //this selects the entire backimage and and paints
          //it on the new image in the same size, so its not distorted.
          canvas.DrawImage(backImage,
                    new Rectangle(0, 0, backImage.Width, backImage.Height),
                    new Rectangle(0, 0, backImage.Width, backImage.Height),
                    GraphicsUnit.Pixel);

          //this paints the frontimage with a offset at the given coordinates
          canvas.DrawImage(frontImage, 5, 25);

          canvas.Save();
        }

        using (MemoryStream memoryStream = new MemoryStream())
        {
          // in this case i needed to return a webimage,
          //but you could simply save it to disk, or return a byte array.
          //Again, be sure to save in a format that supports transparency,
          //such as Png does.
          bitmap.Save(memoryStream, ImageFormat.Png);
          return new WebImage(memoryStream);
        }
      }
    }

Using this method, the result is this:

The finished image

The finished image

It’s kinda hard to see the transparency, so here is a screenshot from Paint.Net that shows transparency as a checkerboard pattern:

Finished Image as seen in Paint.Net

Finished Image as seen in Paint.Net

Remember to use a format that supports transparency, such as Png does.

Enjoy!

Please leave a “Like” and/or use the share buttons, if you found this guide usefull

Yeah! I finally got around to upgrading to Visual Studio 2013. Unfortunately the new version forgot that I did not like the menu to SCREAM AT ME WITH ALL CAPITAL LETTERS!!!11!! So I needed to change it to Normal casing, like I did in VS2012.

Here’s how I did it:

There’s the smooth sailing way and the old school, more complicated way:

Smooth sailing:

Simply run this command i Powershell (in a single line):

Set-ItemProperty -Path HKCU:\Software\Microsoft\VisualStudio\12.0\General -Name SuppressUppercaseConversion -Type DWord -Value 1

BAM! You are done. Restart Visual Studio and enjoy!

Old school:

If you do not have Powershell or simply like to live your life on the edge, go straight into the registry and mess around yourself:

  1. Open regedit
  2. Navigate to “HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\General”
  3. Create a DWORD value with the content “SuppressUppercaseConversion”
  4. Set its value to 1
  5. Pray you did not screw up your registry
  6. Close regedit and restart Visual Studio

Enjoy!

Please leave a “Like” and/or use the share buttons, if you found this guide usefull

This week I had a task where I had to fetch an image and resize it before sending it to the requesting client. This had to be done on a ASP.NET webserver in C#.

It has been some years since I had to do a image resize last time. Back then I used the GetThumbnailImage method on the Image class, but I figured that I better had to do a bit of Googeling to see if there’s something smart around nowadays. Turns out there is!

WebImage class of the System.Web.Helpers.dll

In the System.Web.Helpers namespace of the likewise named dll, Microsoft made the WebImage class. This class has a constructor that takes a URL string and fetches an image and a handy Resize method that makes resizing a single line command. Job done!…. well not quite, in my case. It turns out that the WebImage class does not handle redirects, when downloading the image. And in my case there was not one, but two redirects in most cases before the image was returned.

Handling redirects when requesting an image

So how did I handle the redirects? Here’s how:

public static WebImage GetWebImageFromUrl(string imageUrl)
{
  try
  {
  HttpWebRequest request =
                 (HttpWebRequest) WebRequest.Create(imageUrl);
  request.AllowAutoRedirect = true;
  request.MaximumAutomaticRedirections = 4;

  HttpWebResponse response = (HttpWebResponse)request.GetResponse();

  if ((response.StatusCode == HttpStatusCode.OK ||
       response.StatusCode == HttpStatusCode.Moved ||
       response.StatusCode == HttpStatusCode.Redirect) &&
       response.ContentType.StartsWith("image",
                StringComparison.OrdinalIgnoreCase))
       {
        using (Stream inputStream = response.GetResponseStream())
        {
            return new WebImage(inputStream);
        }
       }
       return null;
  }
  catch (Exception ex)
  {
    Log.Error(string.Format("Error downloading image from url '{0}'.
        Message: '{1}'.", imageUrl, ex.Message), ex);
    return null;
  }
}

Using this method, you can even set credentials, cookies and whatnot on the HttpWebRequest.

Resizing the image

Using the WebImage class, resizing is very easy. It even has two boolean properties to control whether or not to keep the aspect ratio and whether or not the image can be larger than original size:

public static WebImage ResizeImage(WebImage image,
                            int width, int height)
{
  return image.Resize(width, height, true, true);
}

Enjoy!

Please leave a “Like” and/or use the share buttons, if you found this guide usefull

Sitecore tackled

Small posts about Sitecore and solutions

Cooking with Sitecore

Diary of my experience working on great CMS called Sitecore

Visions In Code

Never look back

Cook 4 Passion

Food food fooooood. We love fooooooooood !!!

Eldblom

Sitecore, Digital Marketing, Work, Life and so on...

SitecoreJunkie.com

Down the DLL Rabbit Hole

frontendrush

Arash Sarfehjou

DotNetCoder.dk

.NET code and tweaks

.NET code and tweaks

The grumpy coder.

.NET code and tweaks

Alan Coates - Sitecore/.NET blog

Pushing Sitecore to the limits and beyond

Patrick Delancy

i write code

Laub plus Co

.NET code and tweaks

iStern Blog

A simple Code Blog

Brian Pedersen's Sitecore and .NET Blog

Sitecore, C#, ASP.NET for developers