Notes from Daily Encounters with Technology RSS 2.0
 
# Saturday, January 21, 2012

The more there are developers committing changes to the project source code and the more distributed they are, the more challenging it becomes to keep track of all the changes. Without having enough test coverage this is a recipe for new bugs being introduced by less experienced developers not being aware of all the project intricacies. Introducing a source control monitor notifying code owners of changes can be a good way to reduce this risk. Although there are dedicated tools available for this task, this post introduces a simple way to use your existing CruiseControl.NET setup for this task. A similar approach should be possible with other continuous integration servers as well.

This is a basic project configuration which to use for this purpose:

<project name="My Project Monitor" category="SVN Monitor">
    <sourcecontrol type="filtered">
        <sourceControlProvider type="svn">
            <autoGetSource>false</autoGetSource>
            <trunkUrl>$(SvnUrl)My Project/trunk</trunkUrl>
            <executable>$(SvnExe)</executable>
            <username>$(SvnUsername)</username>
            <password>$(SvnPassword)</password>
        </sourceControlProvider>
        <inclusionFilters>
            <pathFilter>
                <pattern>/trunk/**/*.cs</pattern>
            </pathFilter>
            <pathFilter>
                <pattern>/trunk/**/*.vb</pattern>
            </pathFilter>
        </inclusionFilters>
    </sourcecontrol>
    <triggers>
        <intervalTrigger seconds="60" />
    </triggers>
    <publishers>
        <xmllogger />
        <email from="$(MailFrom)" 
               mailhost="$(MailServer)" 
               mailhostUsername="$(MailUsername)" 
               mailhostPassword="$(MailPassword)" 
               includeDetails="true">
            <subjectSettings>
                <subject buildResult="Success" 
                         value="SVN Monitor: My Project" />
            </subjectSettings>
            <users>
                <user name="Developer 1" 
                      group="CodeOwner" 
                      address="developer.1@mycompany.com" />
            </users>
            <groups>
                <group name="CodeOwner">
                    <notifications>
                        <notificationType>Success</notificationType>
                    </notifications>
                </group>
            </groups>
        </email>
    </publishers>
</project>

A couple of things worth noticing about it:

  • To simplify maintenance of a large configuration file I’m using preprocessor text constants, i.e. values for all $(ConstName) placeholders are defined at the beginning of the configuration file.
  • In the sample above Subversion is used as the source control system, though CruiseControl.NET comes with built-in support most if not all source control systems available today, meaning that unlike dedicated desktop based tools you can use it no matter which and have many different source control systems you are using.
  • Filtered source control block allows additional filtering of detected changes, by both including and excluding certain changes. In my case I’m simply filtering changes by file extension but there are other types of filters available as well. By additionally using a multi source control block you could also monitor multiple repositories in different source control systems with a single project.
  • Setting the autoGetSource property to false, prevents the sources being retrieved from the source control system. This avoids unnecessary delays and network traffic.
  • Triggers give great flexibility over how you want the notification to happen. In my case the project triggers every minute making the notification immediate but you could also configure the notification to happen less often or even only once a day at a specific time (e.g. at the beginning of the work day).
  • Sending out emails to notify developers works great in enterprise scenarios when you need to notify a selected group of people. By setting the includeDetails property to true the list of changes is included in the emails being sent out. A custom email subject makes it easier for the recipients to filter the incoming emails.
  • Including the default XML log publisher insures that the build logs containing all the changes are also generated on the server making it possible for everyone interested to see all past changes at a later time.
Saturday, January 21, 2012 2:07:10 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Software | CruiseControl | Subversion
# Saturday, January 14, 2012

NuGet is a valuable tool for managing references to external libraries in your projects. If you’re not using it yet, you owe it to yourself to try it out and see what you’re missing. Though, that’s not what this post is about. Not only are NuGet packages a great way to distribute publically available libraries, they can be used just as well for custom internal libraries with their own release management which are used in multiple projects. Since there’s a lot of information already available on this topic, instead of repeating it I’ll rather link to it from one place and add a few helpful hints and tricks along the way.

The first step is to create a NuGet package from your library. To do it you need NuGet.exe, it’s not enough to have NuGet Package Manager Visual Studio extension installed, neither is that necessary when this step is being done on your build server. Although it is possible to create a package directly from a Visual Studio project, I strongly suggest to put in a little extra effort from the beginning and use a convention based working directory instead. It gives you many more options which you’re going to miss very soon if you do it the easy way. Don’t forget to set the correct version in the manifest file during each build -  it is only done automatically for you when using a project file as the source. This short NAnt task should do the trick (CCNetLabel property contains the desired version since this is being built with CruiseControl.NET):

<xmlpoke file="MyLibrary.nuspec"
         xpath="package/metadata/version"
         value="${CCNetLabel}" />

Once *.nupkg files are being generated on every build of the library, it’s time to set up an internal feed to distribute them. While it is possible to host a proper feed in IIS, a poor man’s version in the form of a file share will work just as well. Just create a shared folder somewhere on your network (e.g. \\buildserver\NuGet) and copy every generated package file into it. Now you can instruct your developers to add this feed to their NuGet configuration and they can start referencing your libraries the same way they are already used to with libraries from the official NuGet gallery:

NuGet Package Manager Package Sources Settings

You could already stop at this point but I’m convinced that you should go one step further and take care of package restore to avoid putting the libraries in your source control system. There are only three easy steps to follow:

  • Open Package Manager Console Window (Tools > Library Package Manager > Package Manager Console menu item in Visual Studio with NuGet Package Manager installed).
  • Run the following commands:
Install-Package NuGetPowerTools
Enable-PackageRestore
  • Instead of the packages folder put the .nuget folder into source control (both are inside the solution folder).

Once this is done, NuGet will always make sure the correct versions of all the packages are present locally before the build starts. There’s even no need to have NuGet Package Manager installed for this to work. There’s only one more change required to make this work flawlessly with the internal feed that we have set up. Open up the NuGet.targets file in the generated .nuget folder and add this feed to the PackageSources property group:

<PackageSources>\\buildserver\NuGet -source https://go.microsoft.com/fwlink/?LinkID=230477</PackageSources>

Without this modification the package won’t be found if NuGet is not properly configured for the user the build is running under (the package sources configuration is stored in %APPDATA%\NuGet\NuGet.config). The second feed in my case is the official one which you should always add as well so that the public libraries can still be found.

Saturday, January 14, 2012 5:30:40 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | NAnt | NuGet | Software | VisualStudio
# Sunday, January 08, 2012

Web.config transformations are a great but often overlooked feature introduced with ASP.NET 4.0. They provide a simple way to define a different configuration for Debug and Release builds of your project by only specifying the differences (typically only connection strings and similar settings) in a separate transformation file while keeping the core of the configuration file common and consequentially making it easier to manage.

Unfortunately files aren’t transformed until the web deployment package is created, i.e. they aren’t part of the core build process. This makes the transformations more difficult to use in some scenarios such as having a different configuration file for automated testing as a part of the build process.

Since the transformation is done by the TransformXml MSBuild task in Microsoft.Web.Publishing.Tasks.dll assembly there is a way to make this work by modifying the project file manually, though. Here is a snippet that I added to my project file (line break in the AssemblyFile added for readability only):

<UsingTask TaskName="TransformXml" 
           AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\
                         v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterBuild">
    <MakeDir Directories="obj\$(Configuration)" 
             Condition="!Exists('obj\$(Configuration)')" />
    <TransformXml Source="Web.Config" 
                  Transform="Web.$(Configuration).config" 
                  Destination="obj\$(Configuration)\Web.config" 
                  StackTrace="true" 
                  Condition="Exists('Web.$(Configuration).config')" />
</Target>

As you can see the transformed configuration file is put inside the obj folder from where I copy it to the desired final location before running the tests. I find this a suitable spot for it unless you are precompiling views in your ASP.NET MVC project. A web.config file anywhere in obj folder brakes the build so you’ll have to put the file elsewhere or make sure you delete it before precompiling the views.

If you want to make this work on your build server without having Visual Studio installed on it, there is one more step remaining. The above mentioned assembly is not installed with .NET SDK meaning that you have to copy it there from your development machine. The file is located in the MSBuild extension folder, i.e. “C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\” by default.

Transformation files displayed under the original fileThis takes care of transforming web.config files during build. How about transforming app.config files and even other XML files in your projects? I guess it would be possible to use the same MSBuild task on them but no Visual Studio support for transforming those files would mean even more tempering with project files to make transformation files appear under the file they are used to transform.

This is where SlowCheetah – XML Transforms Visual Studio extension can help. After installing it you can define transformations for app.config the same way you are already doing it with web.config files. The transformation is part of the build process in this case, i.e. the transformed file is put in its usual spot in the build output folder (usually bin) instead of the original one. It couldn’t get any simpler.

As an added bonus the extension features support for previewing the results of the transformation: after right clicking the transformation file and selecting the Preview Transform command a diff window will open graphically showing the differences between the original and the transformed file. Of course this works with web.config transformations as well making the debugging of transformations much simpler. A good reason in itself to install this extension.

To avoid failed builds on your build server as well as with the other members of your team not having this extension installed it’s best that you copy the SlowCheetah MSBuild targets and the corresponding assembly containing the tasks to your solution directory and put it in source control. In this case you’ll again have to modify the project file to set the new path. Just search for the SlowCheetahTargets property definition and modify the path accordingly (line breaks added for readability):

<PropertyGroup>
    <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">
        ..\_References\SlowCheetah\SlowCheetah.Transforms.targets
    </SlowCheetahTargets>
</PropertyGroup>

Are there any ways to make your life simpler by using configuration transformations in your projects?

Sunday, January 08, 2012 12:34:56 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | ASP.NET | Software | VisualStudio
# Monday, December 26, 2011

DateTime can be a tricky data type to deal with. Not only is there daylight saving time and different time zones to keep in mind but also the range and precision can vary in different systems. You are probably already aware of some differences between .NET framework’s DateTime structure in Transact-SQL’s datetime data type.

Most notable is certainly a different minimum value that can be expressed:

  • In .NET framework all values between January 1st 1 and December 31st 9999 are supported.
  • In Transact-SQL only values between January 1st 1753 and December 31st 9999 are supported.

This usually shouldn’t be a problem unless you are working with historic data. Setting proper minimum value in the user interface is not be a bad idea nevertheless.

You might not be aware of the difference in precision between these two data types, though. In some edge cases this can cause strange and unpredictable behavior. Let’s take a look at the following example (based on an issue that had me mystified for some time):

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t => t.Id == taskId);
    task.CompletedAt = DateTime.Now;
    timestamp = task.CompletedAt.Value;
    context.SaveChanges();
}

using (var context = new TestEntities())
{
    var task = context.Tasks.Single(t => t.Id == taskId);
    Assert.GreaterOrEqual(timestamp, task.CompletedAt);
}

The assertion in the above code will occasionally fail with a message similar to this one:

SampleTest has failed:
  Expected: greater than or equal to 2011-12-26 19:04:28.313
  But was:  2011-12-26 19:04:28.312

If you’re not familiar with entity framework, here’s what’s going on:

  • In the first code block a DateTime value is stored to the database.
  • In the second code block that same value is reloaded from the database.
  • The value from the database is compared with the one stored in a local variable the whole time.

The strange behavior is caused by the fact that milliseconds get rounded in the database: to increments of .000, .003, or .007 seconds, as it is stated in the documentation. The DateTime value can therefore be different when reloaded from the database, hence the occasional failed assertion. While the problem might be fairly obvious in the simplified example above, it can be much more difficult to pinpoint in a larger chunk of code where there could be other reasons for the values to differ. Even more so if you’re not even aware of the rounding.

Knowing this might save you a couple of hours once.

Monday, December 26, 2011 7:28:18 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | SQL
# Monday, December 19, 2011

In a previous post I addressed the issue of using HTTP module based authentication in WCF. The presented solution worked in most cases but failed completely with Windows authentication. In this post I’ll describe the necessary changes to make this work as well.

Let’s first see what goes wrong with the existing solution and why. To configure WCF for Windows authentication, the following changes are required in web.config:

<system.serviceModel>
    <!-- ... -->
    <bindings>
        <basicHttpBinding>
            <binding name="HttpWindowsBinding" 
                     maxReceivedMessageSize="2147483647">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service name="WcfAuthentication.Service">
            <endpoint address="windows"
                      binding="basicHttpBinding"
                      bindingConfiguration="HttpWindowsBinding"
                      contract="WcfAuthentication.IService" />
        </service>
    </services>
</system.serviceModel>

Of course the settings have to be matched in IIS: Windows authentication should be enabled for the application while anonymous authentication should be disabled, as well as all the other types of authentication.

After setting all this up any calls to our service will throw a MessageSecurityException: "The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'." If you try searching the web for solutions, you’ll notice the same error pops up in many different situations not related to our case. So what’s going on here?

The problem is being caused by the following method in HttpAuthenticationModule:

void context_AuthenticateRequest(object sender, EventArgs e)
{
    HttpContext.Current.User = ProcessAuthentication();
}

Setting the user in the current HttpContext to a custom IPrincipal implementation confuses WCF which expects a WindowsPrincipal as configured. The only way to make it work is to pass through the original user information in this case:

void context_AuthenticateRequest(object sender, EventArgs e)
{
    if (!(HttpContext.Current.User is WindowsPrincipal) && 
        HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.EndsWith(".svc"))
        HttpContext.Current.User = ProcessAuthentication();
}

The extension based filtering is there so that the authentication will still work for the rest of our web application. This change alone is not enough, of course. We still to need the authentication somewhere for the WCF case. HttpContextAuthorizationPolicy is the right spot for it. Evaluate method should be modified as follows:

public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
    HttpContext context = HttpContext.Current;

    if (context != null)
    {
        if (context.User is WindowsPrincipal)
        {
            IPrincipal principal = HttpAuthenticationModule.ProcessAuthentication();
            evaluationContext.Properties["Principal"] = principal;
            evaluationContext.Properties["Identities"] = new List<IIdentity> { principal.Identity };
        }
        else
        {
            evaluationContext.Properties["Principal"] = context.User;
            evaluationContext.Properties["Identities"] = new List<IIdentity> { context.User.Identity };
        }
    }

    return true;
}

Keep in mind that calling a static method in HttpAuthenticationModule to authenticate the user is just a shortcut to make this sample work and is not suggested practice. In production code you’ll want to have your authentication logic implemented somewhere in the business layer and call it from both HttpAuthenticationModule and HttpContextAuthorizationPolicy.

Monday, December 19, 2011 9:12:16 PM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | ASP.NET | WCF
Sponsored Ads

About Me
Twitter
Support charity with the Humble Bundle Mojam livestream event! http://t.co/9c91hoB9 via @humble 4 days ago
Damir's Corner: Peculiarities of Subversion Path Based Authorization http://t.co/YTFpisrY 4 days ago
These 50 Photos Will Blow you Away http://t.co/HeD6HWit via @photoshoptalent 4 days ago
Another good reason for everyone to rather use Virtual CloneDrive instead http://t.co/ecLmrjZb 9 days ago
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2012, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.