Feb 26 2010

Updated Neovolve BE support in CodePlex

Category: My Software | .NetRory Primrose @ 15:37

I have released the new versions of my BE related projects in CodePlex.

Neovolve.BlogEngine.Web 1.1

Neovolve.BlogEngine.Net.Web 1.1 contains a redirector module that translates Community Server url formats into BlogEngine.Net urls. This module will redirect Community Server pages, posts, month post lists, day post lists, tags, syndication and tagged syndication urls to the most appropriate location in BlogEngine.Net. BlogEngine.Net relies on its own friendly written urls when the urls are processed. This module cannot rewrite Community Server urls as BlogEngine.Net will not be able to understand what the requested resource is. The module must redirect requests to the equivalent BlogEngine.Net friendly url so that BlogEngine.Net url writing can occur such that resources are resolved correctly.

In Community Server, tags and categories are the same thing and it supports tag filtering by allowing multiple tags to be defined. BlogEngine.Net supports both tags and categories as separate entities and has a concept of a category hierarchy, but doesn't support tag filtering. When a Community Server url is encountered where multiple tags are defined, the first Community Server tag in the url that can be matched to either a BlogEngine.Net category or tag will be the resource used to response to the client request. Preference is given to categories over tags.

Neovolve.BlogEngine.Extensions 1.2

Contains updated CatTagLink, Snippets and SyntaxHighlighter extensions.

Tags: ,

Feb 17 2010

Recommended reading for developers

I was reminded this morning of an email that I sent to the junior developers on my team when they joined us. It is an overview of some of the development practices, patterns and products that they would get exposed to on our project. I have included it here as a reference collection for others.

Principles and Patterns

These are things that I often use and are still learning to use.

Jeremy Miller also writes a series called Patterns in Practice for MSDN Magazine (see list at http://msdn.microsoft.com/en-au/magazine/cc720886.aspx). They are all a good read, especially:

Tools

These are tools that are good to get experience using. Most of them relate to the patterns above. There are other tools used like ReSharper, dotTrace, StyleCop, WinMerge etc, but they don’t have the up skill requirement that the following tools do.

Probably the most important tool to start using is Rhino Mocks. The only way to get experience with it is to start writing unit tests in VS. See the documentation at http://ayende.com/wiki/Rhino+Mocks+Documentation.ashx.

Tags: , , , , , , , , , , , , , ,

Feb 11 2010

SyntaxHighlighter 2.1 extension released for BlogEngine

Category: .NetRory Primrose @ 10:05

I have created a new version of my SyntaxHighlighter extension for BlogEngine.Net that works with SyntaxHighlighter 2.1. It will work with earlier PRE tag formats from version 1.5 by enabling the Legacy Support option.

This version allows you to define the following options. The default values for the extension are indicated.

SyntaxHighlighter options

Brushes are automatically determined by finding script files that are in the format shBrush*.js. If I don’t want a brush to be included, I just rename its extension from .js to .js.ignored.

SyntaxHighlighter.cs (8.59 kb)

Tags: ,

Feb 11 2010

Snippets 1.2 extension released for BlogEngine

Category: .NetRory Primrose @ 09:35

I have updated my snippets extension for BlogEngine.Net. There are minor bug fixes to a regex that finds html tags and PRE tags are now skipped.

Snippets.cs (12.18 kb)

Tags: ,

Feb 11 2010

Upgrading to BlogEngine.Net 1.6

Category: .NetRory Primrose @ 09:13

Like Dave, I was keen to upgrade my site to the latest BlogEngine.Net release (download here). I did find a few issues with the upgrade though as I was also migrating from ASP.Net user/roles management to the BlogEngine.Net implementation. To help with this process, I wrote a SQL script that did the following:

  1. Enabled error logging (useful for troubleshooting)
  2. Removed the Commentor extension configuration (new comment support is in this release)
  3. Upgraded post contents to migrate from SyntaxHighlighter 1.5 to 2.1
  4. Migrated my permissions for the site from ASP.Net to BlogEngine.Net user/roles (Note: This resets the admin password to blank which will default it to "admin")
  5. Removed all the ASP.Net user/roles objects from the database.

Script is attached.

BE Upgrade 1.5 - 1.6.sql (19.67 kb)

Tags: , , ,

Jan 28 2010

Injecting AppSetting values via Unity

Category: .NetRory Primrose @ 08:14

I've been working with Unity a bit in an enterprise level system and I have been trying to separate objects of different concerns as much as possible. One requirement hit me today where I have a dependency that is resolved from a Unity container. I created a cache dependency layer to go around it, but needed to provide a configuration value to the cache wrapper.

To demonstrate this scenario, consider the following example:

using System;

namespace Neovolve.UnityTesting
{
    public interface IDoSomething
    {
        String Execute();
    }

    public class SomethingDone : IDoSomething
    {
        public String Execute()
        {
            return"Some random value";
        }
    }

    public class CachedSomethingDone : IDoSomething
    {
        private readonly IDoSomething _dependency;

        public CachedSomethingDone(IDoSomething dependency, Int64 maxAgeInMilliseconds)
        {
            _dependency = dependency;
            MaxAgeInMilliseconds = maxAgeInMilliseconds;
        }

        public String Execute()
        {
            // Check cache for value
            // If cache has value and is not too old then return the value
            // If not, get value from dependency, cache it for the next call and return the value

            return _dependency.Execute();
        }

        public long MaxAgeInMilliseconds
        {
            get;
            private set;
        }
    }
}

Unfortunately Unity does not provide a way to resolve a configuration value and inject it into the instance being resolved. This means that the configuration value must be injected as a literal value defined in the unity configuration. While this works, most people think in terms of the appSettings element when configuring the options for their application. This would require them to also review the often complex unity configuration to adjust a required value. I wanted a way to essentially redirect the appSetting value into a unity injection value.

I spent a bit of time cruising around the Enterprise Library source with Reflector to see what could be done about this. Unity natively understands injection configuration for dependencies, literal values and array types. Unity happens to make a call down to InjectionParameterValueHelper.DeserializeUnrecognizedElement() which has a switch over the element name (being value, dependency or array). If the type is not understood then it makes a call out to DeserializePolymorphicElement().

The DeserializePolymorphicElement method is the key. It uses an elementType attribute that gets resolved as InjectionParameterValueElement. This is the point at which Unity can be extended to provide a custom injection implementation. I created an AppSettingsParameterInjectionElement class that is mostly a copy of InstanceValueElement which is the unity definition for injection configuration of literal values. The class looks like the following:

using System;
using System.ComponentModel;
using System.Configuration;
using System.Globalization;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Neovolve.UnityTesting
{
    public class AppSettingsParameterInjectionElement : InjectionParameterValueElement
    {
        public Object CreateInstance()
        {
            String configurationValue = ConfigurationManager.AppSettings[AppSettingKey];
            Type typeToCreate = TypeToCreate;

            if (typeToCreate == typeof(String))
            {
                return configurationValue;
            }

            TypeConverter converter = GetTypeConverter(typeToCreate, TypeConverterName, TypeResolver);

            try
            {
                return converter.ConvertFromString(configurationValue);
            }
            catch (NotSupportedException ex)
            {
                const String MessageFormat =
                    "The AppSetting with key '{0}' and value '{1}' cannot be converted to type '{2}'";
                String settingValue = configurationValue ?? "(null)";

                String failureMessage = String.Format(
                    CultureInfo.InvariantCulture, MessageFormat, AppSettingKey, settingValue, typeToCreate.FullName);
                
                throw new ConfigurationErrorsException(failureMessage, ex);
            }
        }

        public override InjectionParameterValue CreateParameterValue(Type targetType)
        {
            Type type;

            if (String.IsNullOrEmpty(TypeName))
            {
                type = targetType;
            }
            else
            {
                type = TypeResolver.ResolveType(TypeName);
            }

            return new InjectionParameter(type, CreateInstance());
        }

        private static TypeConverter GetTypeConverter(
            Type typeToCreate, String typeConverterName, UnityTypeResolver typeResolver)
        {
            if (!String.IsNullOrEmpty(typeConverterName))
            {
                return (TypeConverter)Activator.CreateInstance(typeResolver.ResolveType(typeConverterName));
            }

            return TypeDescriptor.GetConverter(typeToCreate);
        }

        [ConfigurationProperty("appSettingKey", IsRequired = true)]
        public String AppSettingKey
        {
            get
            {
                return (String)base["appSettingKey"];
            }

            set
            {
                base["appSettingKey"] = value;
            }
        }

        [ConfigurationProperty("typeConverter", IsRequired = false, DefaultValue = null)]
        public String TypeConverterName
        {
            get
            {
                return (String)base["typeConverter"];
            }

            set
            {
                base["typeConverter"] = value;
            }
        }

        [ConfigurationProperty("type", DefaultValue = null)]
        public String TypeName
        {
            get
            {
                return (String)base["type"];
            }

            set
            {
                base["type"] = value;
            }
        }

        public Type TypeToCreate
        {
            get
            {
                return TypeResolver.ResolveWithDefault(TypeName, typeof(String));
            }
        }
    }
}

The configuration for this looks like the following:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <section name="unity"
             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>

  <appSettings>
    <add key="MyTestSetting"
         value="234234" />
  </appSettings>

  <unity>
    <containers>
      <container>
        <types>

          <type type="Neovolve.UnityTesting.IDoSomething, Neovolve.UnityTesting"
                mapTo="Neovolve.UnityTesting.CachedSomethingDone, Neovolve.UnityTesting">
            <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
                                     Microsoft.Practices.Unity.Configuration">
              <constructor>
                <param name="dependency"
                       parameterType="Neovolve.UnityTesting.IDoSomething, Neovolve.UnityTesting">
                  <dependency name="CacheSomething" />
                </param>
                <param name="maxAgeInMilliseconds"
                       parameterType="System.Int64, mscorlib, Version=2.0.0.0">
                  <appSetting elementType="Neovolve.UnityTesting.AppSettingsParameterInjectionElement, Neovolve.UnityTesting"
                              appSettingKey="MyTestSetting"
                              type="System.Int64, mscorlib, Version=2.0.0.0"/>
                </param>
              </constructor>
            </typeConfig>
          </type>

          <type type="Neovolve.UnityTesting.IDoSomething, Neovolve.UnityTesting"
                mapTo="Neovolve.UnityTesting.SomethingDone, Neovolve.UnityTesting"
                name="CacheSomething">
          </type>

        </types>
      </container>
    </containers>
  </unity>
</configuration>

The test application to tie all this together is the following:

using System;
using System.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Neovolve.UnityTesting
{
    class Program
    {
        static void Main(string[] args)
        {
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            UnityContainer container = new UnityContainer();

            section.Containers.Default.Configure(container);

            CachedSomethingDone something = (CachedSomethingDone)container.Resolve();

            Console.WriteLine("Dependency configured with max age: " + something.MaxAgeInMilliseconds);
            Console.ReadKey();
        }
    }
}

In this process I found that it would be nice if the InstanceValueElement class was designed to allow for easier extension. The two likely options here are to allow the CreateInstance method or the Value property to be overridden. This would mean that the above class would only have to resolve the application setting rather than essentially duplicate the logic in InstanceValueElement.

Neovolve.UnityTesting.zip (8.63 kb)

Tags: , , , ,

Jan 15 2010

Filtering items in the MSF 2.0

Category: .NetRory Primrose @ 11:56

I’ve been playing with the Microsoft Sync Framework over the last couple of years. For too long I have been dabbling in a services based project that synchronises data between a set of clients. The system has been through several designs starting with hand-crafted change tracking which was really tricky. The next version used Microsoft Sync Framework on the client manage this process. This didn’t have the best result as there was no central replica for the data held by the service. The third design used a proxy provider so that central metadata information was held by the service. The fourth and latest design completely pushes Microsoft Sync Framework into the service.

The latest design allows clients to simply work with services and not have to have any understanding of Microsoft Sync Framework. There are a few hurdles with this design however. The provider implementation on the server needs to implement a preview sync so it can tell the client what changes needs to happen without doing them at that time. When a change does happens, the client will only action a single change at a time each of which must operate within a sync session in the service. This means that the sync provider also needs to work with a filtered sync session.

I created a POC project to prove that I could actually achieve these features with Microsoft Sync Framework before I invested any more time in the latest design. The POC aims to sync a data item that looks like the following.

using System;

namespace CachedSyncPOC
{
    public class ItemData
    {
        public ItemData()
        {
            Id = Guid.NewGuid().ToString();
            Data = Guid.NewGuid().ToString();
        }

        public String Id
        {
            get;
            set;
        }

        public String Data
        {
            get;
            set;
        }
    }
}

The code aims to store both the Id and the Data of each item in the metadata store of each replica.

Preview mode

This was actually easy to implement and is done in two parts.

The first part is that the provider notifies any interested parties of changes found using a custom event raised in GetChangeBatch.

public override ChangeBatch GetChangeBatch(
    UInt32 batchSize, SyncKnowledge destinationKnowledge, out Object changeDataRetriever)
{
    ChangeBatch batch = Metadata.GetChangeBatch(batchSize, destinationKnowledge); 

    IList changes = new List(batch.Count());
    ItemDataRetriever retriever = new ItemDataRetriever(Metadata);

    foreach (ItemChange change in batch)
    {
        changes.Add(retriever.LoadFromSyncId(change.ItemId));
    }

    OnChangesFound(
        new ChangesFoundEventArgs
        {
            Changes = changes,
            ReplicaId = ReplicaId.GetGuidId()
        });

    changeDataRetriever = retriever;

    return batch;
}

The second part is that the ProcessChangeBatch simply ignores any changes when in preview mode.

public override void ProcessChangeBatch(
    ConflictResolutionPolicy resolutionPolicy, 
    ChangeBatch sourceChanges, 
    Object changeDataRetriever, 
    SyncCallbacks syncCallbacks, 
    SyncSessionStatistics sessionStatistics)
{
    if (IsPreview)
    {
        return;
    }

    // Use a NotifyingChangeApplier object to process the changes. 
    // This object is passed as the INotifyingChangeApplierTarget
    // object that will be called to apply changes to the item store.
    NotifyingChangeApplier changeApplier = new NotifyingChangeApplier(IdFormats);
    INotifyingChangeApplierTarget2 applier = new ItemDataChangeApplier(this, Metadata, Filter);

    changeApplier.ApplyChanges(
        resolutionPolicy, 
        Configuration.CollisionConflictResolutionPolicy, 
        sourceChanges, 
        (IChangeDataRetriever)changeDataRetriever, 
        Metadata.GetKnowledge(), 
        Metadata.GetForgottenKnowledge(), 
        applier, 
        null, 
        SessionContext, 
        syncCallbacks);
}

This example is a little simplistic in that the event does not indicate what action is going to be taken for each item but that should be easily implemented down the track.

Filtering

The Microsoft Sync Framework team has provided many examples on how to use the framework. My initial reaction to the custom filtering sample was one of complete dread. My filtering requirements are simple and the sample code provided is very complex. I posted a question on the Microsoft Sync Framework forum to seek some advice. While the advice was good, it unfortunately pushed me back into the provided filter sample code.

As I started to look through the code, I realised that there were a couple of different types of filtering being demonstrated. I came across a MSDN document about Microsoft Sync Framework filtering (here) and found that what I needed wasn’t actually that complex. I need to filter an item in a session rather than filter a change unit or implement full custom filtering. It is the latter two that are demonstrated in the sync filtering sample code.

You need to update the provider implementation and provide a filter type in order to filter an item in a sync session. The filter type in my example works with the Id property of the filter item and provides logic for comparing filters between providers.

using System;
using Microsoft.Synchronization;

namespace CachedSyncPOC
{
    public class ItemDataFilter : ISyncFilter
    {
        public ItemDataFilter(String id)
        {
            if (String.IsNullOrEmpty(id))
            {
                const String IdParameterName = "id";

                throw new ArgumentNullException(IdParameterName);
            }

            Id = id;
        }

        public Boolean IsIdentical(ISyncFilter otherFilter)
        {
            ItemDataFilter itemFilter = otherFilter as ItemDataFilter;

            return itemFilter != null && Id.Equals(itemFilter.Id);
        }

        public Byte[] Serialize()
        {
            throw new NotImplementedException();
        }

        public String Id
        {
            get;
            set;
        }
    }
}

The provider needs to support a couple of filter interfaces. I need to implement both interfaces as I intend on using the same provider as both source and destination provider.

internal class CustomProvider : KnowledgeSyncProvider, ISupportFilteredSync, IRequestFilteredSync, IDisposable
{
    public void SpecifyFilter(FilterRequestCallback filterRequest)
    {
        if (Filter != null)
        {
            if (!filterRequest(Filter, FilteringType.CurrentItemsOnly))
            {
                throw new Exception("Filter not accepted at source");
            }
        }
    }

    public Boolean TryAddFilter(Object filter, FilteringType filteringType)
    {
        ISyncFilter syncFilter = filter as ISyncFilter;

        if (syncFilter == null)
        {
            return false;
        }

        return true;
    }

    // Rest of class removed for brevity

}

The next change is the GetChangeBatch method needs to deal with the filter. The ChangeBatch returned to the other provider should only contain changes related to the filter. This was the bit I was dreading in the filter process, but the Microsoft Sync Framework makes this really easy for item filtering. The GetFilteredChangeBatch method takes a delegate that determines whether items should be in the filtered change batch or not.

public override ChangeBatch GetChangeBatch(
    UInt32 batchSize, SyncKnowledge destinationKnowledge, out Object changeDataRetriever)
{
    ChangeBatch batch;

    if (Filter != null)
    {
        FilterInfo filterInfo = new ItemListFilterInfo(IdFormats);

        batch = Metadata.GetFilteredChangeBatch(batchSize, destinationKnowledge, filterInfo, ItemFilterCallback);
    }
    else
    {
        batch = Metadata.GetChangeBatch(batchSize, destinationKnowledge);
    }

    IList changes = new List(batch.Count());
    ItemDataRetriever retriever = new ItemDataRetriever(Metadata);

    foreach (ItemChange change in batch)
    {
        changes.Add(retriever.LoadFromSyncId(change.ItemId));
    }

    OnChangesFound(
        new ChangesFoundEventArgs
            {
                Changes = changes, 
                ReplicaId = ReplicaId.GetGuidId()
            });

    changeDataRetriever = retriever;

    return batch;
}

private Boolean ItemFilterCallback(ItemMetadata itemmetadata)
{
    // TODO: Cache this lookup in GetChangeBatch as we don't want to unnecessarily call this for each item checked
    ItemMetadata metadata = Metadata.FindItemMetadataByUniqueIndexedField("Id", Filter.Id);

    if (metadata == null)
    {
        return false;
    }

    return itemmetadata.GlobalId == metadata.GlobalId;
}

That's all there is to it. Not too hard after all.

My POC project is attached to this post for reference.

CachedSyncPOC.zip (21.08 kb)

Tags:

Dec 15 2009

What is the working directory for Windows services?

Category: .NetRory Primrose @ 12:03

I’ve been developing a windows NT service for the last week and I hit an interesting issue today. The configuration for the service contains a relative path which is used in the construction of a class. When this constructor is called, the code checks if the directory exists and creates it if it doesn’t.

The service in question logged errors indicating that there were insufficient privileges for creating the directory. This told me two things. Firstly the directory didn’t exist and secondly there is a permissions problem. I verified that the directory was created by the installer so that means that there is an issue with relative paths.

I quickly realised that the current working directory of a Windows service is probably not the path of the service assembly. Most likely the current directory for a Windows service is C:\Windows\System32. This meant that any work with relative paths was likely to cause grief.

The simple fix for my service is to set the current directory for the process to the directory containing the executing assembly when the service is started.

using System;
using System.IO;
using System.Reflection;
using System.ServiceProcess;

internal static class Program
{
	private static void Main()
	{
		Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		MyService service = new MyService();

		ServiceBase.Run(service);
	}
}

Now any configured relative path will be relative to the service assembly. Problem solved.

Tags:

Nov 18 2009

Is there a point to code coverage?

Category: IT RelatedRory Primrose @ 09:40

Code coverage is a concept that is often misunderstood and misused. It gets some criticism every once in a while because of this.

The most common misconception is that code coverage is a measure of code quality. The name code “coverage” also makes it easy to assume that it is a metric regarding the exhaustiveness of test effort. Neither of these are incorrect.

My definition is that code coverage is a measure of what you haven’t tested. Nothing more, nothing less.

Just because something is covered by a test does not ensure that the code is either of adequate quality nor that all possible scenarios are tested for that code. If it isn’t covered though then it isn’t tested and needs some attention.

Tags:

Oct 23 2009

Using testrunconfig sometimes fails to deploy dependencies

Category: .NetRory Primrose @ 11:45

I’ve never been a fan of deploying test dependencies using testrunconfig. I prefer dependencies to be located as closely as possible to where they are used, ideally on an individual unit test. Using testrunconfig means that the dependencies are deploy at the solution level.

Having dependencies attached to each unit test for my current project has become unmaintainable however as almost all unit tests require the same dependencies. This makes testrunconfig appropriate in this case.

The issue I found with deploying dependencies with testrunconfig is that the dependency is not deployed into the TestResults directory when a new dependency reference is added to the config. This appears to be a bug in Visual Studio where the testrunconfig contents is cached. The workaround is to reload the solution. Each time this happens I have actually closed the IDE and opened the solution again. When the test run is executed the dependencies are not deployed as expected.

Tags: