Post deployment Integration testing using TFS 2012 builds

16. december 2014 17:06 by martijn in tfs2012, testing

Why should I do integration testing?

Although I very much like unit-testing and frameworks like Moq they sometimes miss the big picture. You might have 99% code coverage and a green test suite only to find out later you messed up your environment because you did not register your new code in your dependency configuration or forgot to check-in some other configuration. Every little part of your code was tested but the sum did not work out. What if you could deploy to a test server and run your tests against this server? This is what post-deployment integration testing is about. The process below describes setting up a TFS build definition that does compile, test, deploy and integration-test. If any step fails the build fails. You can combine this with a gated check-in to make sure your environment never brakes. I would recommend to use the lab environment for this if you have set this up already : http://msdn.microsoft.com/en-us/library/hh191495.aspx. The method described here uses just a build controller and build agent.

Describing the process

The proces is a small modification of the normal gated-checkin process of TFS 2012. Only a integration-tests step is added.

Modifying the build template

To get integration testing we need to modify the build in two ways.

  1. Add a integration testing step to the build process. This is basically a copy of the normal unit-testing step with a slight modification. Instead of using the TestSpecs and DisableTest variabeles we use IntegrationTestSpecs and DisableIntegrationTest. I included the definition file for download below.
  2. Make sure your integration test are only run in the integration step and not in the regular unit-testing step. You can accomplish this by using categories for your integration tests. 

 

BuildTestDeployAndTestTemplate.xaml (117.36 kb)

Logging all WCF messages

16. september 2014 10:38 by martijn in

Just as a reminder. Here's how you log all messages for a wcf service. Copy & Paste into web.config.

<system.diagnostics>

    <sources>

      <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">

        <listeners>

          <add name="messages"

          type="System.Diagnostics.XmlWriterTraceListener"

          initializeData="c:\logs\messages.svclog" />

        </listeners>

      </source>

    </sources>

  </system.diagnostics>

  <system.serviceModel>

    <diagnostics>

      <messageLogging

           logEntireMessage="true"

           logMalformedMessages="true"

           logMessagesAtServiceLevel="true"

           logMessagesAtTransportLevel="true"

           maxMessagesToLog="300000"

           maxSizeOfMessageToLog="200000"/>

    </diagnostics>

  </system.serviceModel>

Synching FileZilla settings using Dropbox

23. december 2013 11:28 by martijn in

I love Dropbox. One of the things it allows me to do is have setting files (keys/docs) synched accross my computers without any hassle. Combined with the sitemap.xml of FileZilla and I have easy access to my ftp accounts on all my machines. This howto describes how you can set up FileZilla / Dropbox so your sitemanager is stored on your DropBox.

So how can you set it up?

  1. First copy your FileZilla settings to your Dropbox. For me the settings files were stored in C:\Users\Martijn\AppData\Roaming\FileZilla. Copy the whole folder to your dropbox eg: C:\Users\Martijn\Dropbox\Filezilla
  2. Next we need to change the FileZilla defaults. There is a file called fzdefaults.xml.example in your FileZilla program files 'docs' folder (C:\Program Files (x86)\FileZilla FTP Client\docs). Copy this file to the folder above (C:\Program Files (x86)\FileZilla FTP Client\) and rename it to fzdefaults.xml. FileZilla will pick up this file and use it to find the other configuration files.
  3. Change the Config Location key to point to your Dropbox FileZilla folder of step 1

 

That's it! Happy synching!

Creating C# from XML

10. november 2013 10:56 by martijn in

Sometimes you have a piece of XML and quickly want to get the 'matching' c# classes so you can deserialize it. There is a website for this :)

http://code-w.com/Tools/Xml-to-Class-Generator

Just paste in your XML and get C# classes in return. Nice :)

 

Creating a simple logging Interceptor using NInject 3.0

8. oktober 2013 20:52 by martijn in .net, DRY, ninject

One of the really cool aspects of Depency Injection is the ability to add functionality without changing existing code. A typical example of this might be implementing INotifyPropertyChanged or logging method calls. Using NInject 3.0 Interceptors it is very easy to do this. The interceptor intercepts all calls to the resolved object and allows you to add logging or whatever code you want to run. In NInject 3.0 the methods you intercept do NOT have to be virtual as well :) So how to set it up...

Getting the right assemblies.

Using Nuget just get NInject.Extensions.Interception.Linfu. This will also setup NInject 3.0 and NInject.Extensions.Interception.

 

Creating the logging Interceptor

This is just a sample interceptor that logs using Console.Writeline. Normally you would call something like Log4Net or your preferred logging framework. Implementing IInterceptor means you have to implement a Intercept method. The Intercept method gets a invocation as a parameter. By invocation.Proceed() the original method gets called. The logger first logs the method being called and the arguments it is called with. After the invocation.Proceed() it logs the result of the method call. The interceptor is pretty simple and can certainly be improved by creating nicer more custom messages.

public class LoggingInterceptor : IInterceptor

    {

        public void Intercept(IInvocation invocation)

        {

            var methodName = invocation.Request.Method.Name;

            try

            {

                var parameterNames = invocation.Request.Method.GetParameters().Select(p => p.Name).ToList();

                var parameterValues = invocation.Request.Arguments;

 

                var message = string.Format("Method {0} called with parameters ", methodName);

                for (int index = 0; index < parameterNames.Count; index++)

                {

                    var name = parameterNames[index];

                    var value = parameterValues[index];

                    message += string.Format("<{0}>:<{1}>,", name, value);

                }

 

                //log method called

                LogMessage(message);

 

                //run the intercepted method

                invocation.Proceed();

 

                //log method return value

                if (invocation.Request.Method.ReturnType != typeof(void))

                {

                    LogMessage(string.Format("Method {0} returned <{1}>", methodName, invocation.ReturnValue));

                }

 

            }

            catch (Exception ex)

            {

                var message = string.Format("Method {0} EXCEPTION occured: {1} ", methodName, ex);

                LogMessage(message);

                throw;

            }

        }

 

        private static void LogMessage(string message)

        {

            Console.WriteLine(string.Format("{0:HH:mm} {1}", DateTime.Now, message));

        }

    }

 

 

Adding the logging interceptor to your NInject Configuration

In your kernel configuration you can add interceptors to your bindings like this :

kernel.Bind<IService>().To<Service>().Intercept().With<LoggingInterceptor>();

Now when getting a IService using Kernel.Get<IService> the logginginterceptor will be interception all method calls :) A working sample console application can be found here: 

SampleLogging.rar (2.86 mb)

SampleLogging.rar (2.86 mb)

 

 

 

Globalizing MVC razor views using cshtml per locale

30. juli 2013 21:33 by martijn in .net, globalization, MVC

There are quite a few ways to localize your MVC applications. The best is probably to reference resources (resx) from your cshtml files. For a overview see this complete guide and the post by Hanselman

This can be a bit awkward though if you need a different structure for a different country. Another option is to use a cshtml file per locale. For example use a index.nl.cshtml file for dutch users and index.cshtml for other users. How to do this is the topic of this post. Be aware that this should not be your first choice because you basically copy your HTML making changes later on harder. It can be good to know this trick sometimes... (If you use WebForms viewengine you should use this guide.)


To get this working we need to complete a few steps

  1. Create a localized view
  2. Create a viewengine that prefers localized views and uses the default view if none is found. This makes localization optional and nice to combine with other (resource based) solutions.
  3. Register the ViewEngine in global.asax

Create a localized view

How you structure your views is arbitrary. For this post I post the localized direct next to the normal view. Here I created a Index for the dutch (nl) locale:

Creating the globalized ViewEngine

We subclass the normal RazorViewEngine and only change the part that determines which file is used. We use the CurrentUICulture of the current thread to determine which culture should be used. Then we check to see if there is a view specific for this culture. If no specific view is found the regular view is used.

using System;
using System.IO;
using System.Web.Mvc;
namespace LocalizedViews
{
public sealed class RazorGlobalizationViewEngine : RazorViewEngine
{
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
partialPath = GlobalizeViewPath(controllerContext, partialPath);
return base.CreatePartialView(controllerContext, partialPath);
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
viewPath = GlobalizeViewPath(controllerContext, viewPath);
return base.CreateView(controllerContext, viewPath, masterPath);
}
private static string GlobalizeViewPath(ControllerContext controllerContext, string viewPath)
{
var request = controllerContext.HttpContext.Request;
var lang = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
if (!string.IsNullOrEmpty(lang) && !string.Equals(lang, "en", StringComparison.InvariantCultureIgnoreCase))
{
string localizedViewPath = viewPath.Replace(".cshtml", "." + lang + ".cshtml");
if (File.Exists(request.MapPath(localizedViewPath)))
{
viewPath = localizedViewPath;
}
}
return viewPath;
}
}
}

Registering the ViewEngine in global.asax

We can register the viewengine in the global asax like this:

 protected void Application_Start()

        {

            ViewEngines.Engines.Clear();

            ViewEngines.Engines.Add(new RazorGlobalizationViewEngine());

           //the rest of it..

        }

And that's all there is too it. Happy coding!

Creating DbGeography from Lat Lon

14. juni 2013 12:17 by martijn in dbgeography, entity framework

One of the trivial things I missed in EF5 DbGeography is a way to create a DbGeography from lat lon. I created a helper for just that:

 

public static class DbGeographyHelper

{

    public static  DbGeography FromLatLon(double lat,double lon)

    {

        var p1 = string.Format("POINT({0} {1})", lon, lat);

        return DbGeography.FromText(p1);

    }

}

 

 

Enjoy!

Using bundling to generate base64 encoded images in CSS

9. juni 2013 14:59 by martijn in .net, bundling, css

Should I use base64?

 

In this era of optimization and mobilization having a lot of request to load your website is considered a bad thing. One of the things you can do is 'inline' your images in your CSS file using a base64 format. This way the browser can get the CSS and the images in one big request.

There are some cons to this :

  • Images are not cached separately and when you change your css the download will be bigger.
  • IE6 and IE7 don't support base64 images in CSS. You can use a fallback tag for these browsers.
  • Your development gets more complex as you have to remember to update the base64 images in your css when you modify an image.
  • Images in css are about 37% larger than in a separate file.
  • Works for images up to 37k in IE8
  • Stylesheets get really large 

Also you might consider using a spritesheet which can be cached seperately (like jQuery UI does for example) or create a separate stylesheet for your inlined-images so your cache will not be invalidated when you change something else in you stylesheet. Some more considerations and opinions at Stackoverflow....

Creating a bundle transform to inline the images

So still interested? Some of the development disadvantages can be avoided by using a bundle transform. A bundle transform is part of the System.Web.Optimization library by Microsoft. The basic idea of bundling is combining multiple css or jss files into one big file at runtime. You can configure System.Web.Optimization to only optimize when you are in release mode so that during development you have separate readably resources. This post is about creating a bundle that replaces background-image:url('/yourimage') which base64 urls during optimization.

As you can see the image is inlined (in the 28796 characters) and a fallback for IE6/IE7 is supplied as well. 

This can be done at development time easily with the web essentials extension by Mads Kristensen. The idea of this transform is to perform the operation at runtime. The main advantage is that your development is not cluttered with having to regenerate images and having optimization only on production code.

Here's the code

So let's get into the details. Sorry for the missing syntax highlighting. I have not fixed that yet.

[code:c#]

 public class CssBaseEncodeTransform : IBundleTransform

    {

        public void Process(BundleContext context, BundleResponse response)

        {

            response.Content = InlineBase64BackgroundImages(response.Content, BundleTable.MapPathMethod);

        }

 

        public static string InlineBase64BackgroundImages(string content, Func<string, string> mappath)

        {

            //find background-images

 

            var parser = new CSSParser();

            var cssDocument = parser.ParseText(content);

            foreach (RuleSet rule in cssDocument.RuleSets)

            {

                var declarations = rule.Declarations.ToList();

                foreach (var declaration in declarations)

                {

                    if (declaration.Name == "background-image")

                    {

                        rule.Declarations.Add(GetIe6Declaration(declaration));

                        EmbedUrlInBackground(declaration,mappath);

                    }

                }

            }

 

            return cssDocument.ToString();

        }

 

        private static Declaration GetIe6Declaration(Declaration declaration)

        {

            var copy = new Declaration();

            copy.Expression = new Expression()

                {

                    Terms = new List<Term>{new Term() {Value = declaration.Expression.Terms.First().Value}}

                };

            copy.Name = "*background-image";

            return copy;

        }

 

        private static void EmbedUrlInBackground(Declaration declaration, Func<string, string> mappath)

        {

            var imageUrl = declaration.Expression.Terms[0].Value;

            var image = Image.FromFile(Path.GetFullPath(mappath(imageUrl)));

            var data = ImageToBase64(image, ImageFormat.Jpeg);

            var url = string.Format(@"data:image/jpg;base64,{0}", data);

            

 

            declaration.Expression.Terms[0].Value = url;

        }

 

 

        public static string ImageToBase64(Image image,ImageFormat format)

        {

            using (MemoryStream ms = new MemoryStream())

            {

                // Convert Image to byte[]

                image.Save(ms, format);

                byte[] imageBytes = ms.ToArray();

 

                // Convert byte[] to Base64 String

                string base64String = Convert.ToBase64String(imageBytes);

                return base64String;

            }

        }

    }

[code]

  1. The code basically looks for background-image declarations in your style sheet.
  2. If found replace the url('/image') with the base64 equivalent.
  3. A *background-image declaration is added for IE6/7 support.

Usage

Just add the transform to the bundle :

The code use the simple css parser project which can be found here (and is included in the zip). The source code is also included at the bottom. Hope is this of some use or inspiration!

Base64Bundling.zip (997.47 kb)

 

Creating a three column responsive layout with one fixed and two fluid columns

4. juni 2013 20:33 by martijn in css, design, html, responsive

Today I want to give a sample of a way you can create a semi-fluid layout. By semi-fluid I mean some columns in your layout have a fixed size and others work with percentages. This is especially usefull if you are doing responsive design. The finished demo can be found here

 

Html Structure

The basic sample consist of the following html:

 

    <div class="wrapper">
        <aside>           
        </aside>
        <div class="col1">           
        </div>
        <div class="col2">           
        </div>
    </div>
 
We have a wrapper div that contains all three columns, we have a aside for our left or right column. In this sample I will place it left. There is a column in the middle taking up 2/3 of the width for our main content. And a column on the right taking up the remaining 1/3. 
 

Positioning with border box and padding

To positions the divs next to other we use a float left and give percentages of 66% and 33%. If we then give a fixed width to the aside you will find that the wrapper is wider than the 100% that 66 + 33 is supposed to be. This is because the width of the aside is not substracted before the percentages are calculated. One way to work-around this is by using the border-box css property and some padding on our wrapper div. By setting a padding-left on the wrapper we create a space of absolute position which is not included in our 100% when we use 'border-box' sizing on our wrapper. To read more about 'border-box' I recommend the post by Paul Irish on this topic Now we have a empty padding space we can move in the aside by giving that an absolute position of 0,0 and a relative position on the wrapper. That way the aside is always in the top left corner of the wrapper. See this first step here
 

Adding some responsiveness

In a responsive design you might want remove the aside and replace it with a toggle menu or some other element. Removing the aside is easy : all we have to is set its display to none and remove the padding from the wrapper so our remaining columns can take the full 100%. We do this when the screen gets below a certain width in a media query :
        
        @media screen and (max-width: 700px)
        {
            aside
            {
                display: none;
            }
 
            .wrapper
            {
                padding-left: 0;
            }
        }
 
When we use an even smaller device we might even prefer a single colum layout. In order to do this we simply give our columns the full 100% width below some screen width in a another media query:
 
        @media screen and (max-width: 500px)
        {
            .col1, .col2
            {
                width: 100%;
            }          
        }
 
This step can be seen here

Adding some fancyness

To really top it off we might want to animate the removal the side bar by sliding it off to the left. This is easy to do with a CSS transition. Support for this is still limited though now (no IE9 but IE10 is OK) so i would stick with a jQuery sollution for production environments. To slide we animate both the 'padding of the wrapper and the left property of the aside. The aside moves of the screen as the padding gets smaller creating a nice effect.
        .wrapper
        {
            transition: padding 0.5s;
        }
 
        aside
        {
            transition: left 0.5s; 
        }
 
Now in a media query we change both the padding and left.
        @media screen and (max-width: 700px)
        {
            aside
            {
                left: -200px;
                
            }
 
            .wrapper
            {
                padding-left: 0;
            }
        }
 
The final demo is here
I hope this is off some use to you!

 

Generating TypeScript proxy classes for Ajax Methods using Weld

1. juni 2013 19:30 by martijn in .net, jQuery, MVC, typescript, Weld

In this post I want to talk about a little tool called Weld I wrote to make integrating client-side TypeScript and server side MVC C# easy. 

Imagine you have a server-side method that calculates some value you want to use client side. In this sample project I want to calculate the sum of two values I have in input fields.

image

image

Server-side I have this action-method in my home controller.

public int Sum(int x,int y)
{
return x + y;
}
Now to access this method client I just need to add a Weld attribute. For this I first install Weld using NuGet. 
Just “Install-Package Weld” in your NuGet package manager console. This will install Weld as well a TypeScript.Compile and JQuery typings into your project. 
TypeScript.Compile auto compiles all your typescript files post-build. This enables you to detect any problems caused by server side changes. 
The basic process :
  1. Normal compilation
  2. Weld generates TypeScript code for the classes your decorated with Weld attributes
  3. TypeScript compiles all files in your project with build actions 'TypeScriptCompile'
For this sample I add the AjaxMethod (Weld.Attributes.AjaxMethod) attribute to the ‘Sum’ action. 
Compile the project. Weld now has generated a proxy class for my home controller. I just need to include it and used it in the project. It is located in the /Scripts/Weld folder. 
I add the generated homecontroller.ts to my project. I my main TypeScript file I write the following to hook it all up:
/// <reference path="Weld/HomeController.ts" />/// <reference path="typings/jquery/jquery.d.ts" />
$(document).ready(function () {
$("#btnSum").click(function () {
HomeController.prototype.Sum($("#number1").val(), $("#number2").val(), (result) => {
$("#result").text(result);
});
});    
});
As you can see the details of the Ajax communication are handled by weld and you get a nice interface to your server side API :)