Sep 30, 2011

Yet another scripts and styles combining and minification in ASP.NET

In recent project we had to optimize application for mobile devices with slow internet connection. Obviously among other we need to combine, minify and gzip scripts/styles to reduce their size. And that’s how project I’m going to describe here has started. Its free, open source and hosted on bitbucket.

Examples on how to use it you can find on the wiki page. Here I want describe a little about how it it done and how it works.

nuget

Of course I’ve created a nuget package Smile. During installation it registers required http handler and creates required configuration section. The only issue I can see here is that when you are going to update on new versions it may reset your adjustments in configuration. But currently its not a lot of them so you can restore it.

Rendering

During debug mode all the scripts/styles references will be outputted separately and non minified. Its useful for debugging and development.

In release mode all the references are combined in single style/script reference with query string looking something like:

/Scripts/assets.axd?js=jquery-1.4.1,main&cache=akqipjXPAq2UFLgARybjJ9QwjiA%3d

In this case client browser will do less web requests for the page and will receive all the static content in one go.

Client side cache

URL for assets has two parameters. File names and cache. Meaning of first one is obvious, but the second one is more interesting. It is SHA1 code of combined file contents of all assets that are included in this reference. So if you change any of that scripts this parameter will change. It gives us the ability to easily allow public caching of results for the reference meaning that even proxy servers will cache it. And the uniqueness of this URL will allow you to update files without asking users to press ctrl + f5 in order to get new version of content.

Server side cache

On server side two things are cached.

Minified js and css files. Its obvious that we shouldn’t minify files on each request, so its done once and placed in cache. Also each minified cache entry has a cache dependency on file system meaning that if you change file it will expire the cache. So you can modify static content just in production without any restrictions – new file will be delivered on next request.

Digital signature. signature is calculated once and is places in cache. It also has a dependency on files its signing. So if anything changes, signature will also change.

Unit tests

I’ve tried MSpec on this project as testing framework. And I really liked it. For me the main problem in tests was the test fixture setup. It was always bigger than action, code under test and results verification part.  But look at this test:

[Subject(typeof(AssetsHandler))]
public class When_compress_is_true_and_client_accepts_gzip : compression_spec
{
    Establish context = () => {
        Compress = true;
        AcceptEncoding = "gzip";
    };

    Because of = () => handler.ProcessRequest(httpContext.Object);

    It should_set_gzip_response_filter = () => 
        response.Filter.ShouldBeOfType<GZipStream>();

    It should_set_gzip_response_header = () => 
        responseMock.Verify(x => x.AppendHeader("Content-Encoding", "gzip"));
}

Its just great! All unnecessary code ceremony is moved to compression_spec class. In the test itself you see only required part.

Where to store script references before rendering?

In order to output all references at one go assets optimizer needs a place where to accumulate all required references. In ASP.NET its easy to implement because we have an AssetsManager control. During Init event it places this pointer into Page.Items state (before writing this manager, I didn’t know this state even exists Smile) and verifies that no other assets managers has placed themselves to this storage. Each proxy object in own event just finds that single manager in page state and registers all the styles and scripts there.

In ASP.NET MVC it’s a little bit more interesting. We don’t have manager there and need to find another state where to store references. The best place for the references I’ve found is HttpContext.Items. So each call to Assets.Script or Assets.Style just places a reference and renders nothing. And when Assets.Render() is called all the collected references are picked up from HttpContext. So if some of your scripts are not rendered, make sure that you register it before Render  method is called.

What next

What next I think would be useful:

  1. Components – ability to output assets in groups, not in one go
  2. Control over order – maybe automatic, maybe by providing some king of sort order property that developer could set
  3. Routing – nice url for handler

Jul 22, 2011

Slides and code

I promised to publish slides and code from my talk about unit testing. Here they are:

And a source code:

Jun 9, 2011

Getting started with NHibernate and ConfOrm (revamp)

I’m trying to post different things about NHibernate, but still post NHibernate for beginners is most popular. I wrote them in 2009 (Wow, how old I am! :D). First of all its in Russian and I think things have changed a bit since that time, mainly because of awesomeness of NuGet. This getting started will contain not only recommended mapping technique, but also references to some other useful things like GetHashCode, Equals implementations, transactions management, etc.

So lets get started. First of all install NuGet. Create a new empty MVC 3 project and add two class library projects name them %WhatYouLike%.Core and %WhatYouLike%.Data. First assembly will contain all business entities that NHibernate will save and load from data base. Data assembly is going to be used for NHibernate configuration, repositories, etc.

So when projects are created lets install NHibernate. In visual studio navigate to Tools –> Library Package Manager –> Package Manager Console. In the opened command prompt select your MVC project as default project and execute command: “Install-Package ConfOrm”. Do the same for Data project.

ConfOrm is an open source project that allows you to map all your domain model without any XML. I do use ConfOrm instead of Fluent NHibernate in this example just because first one is going to be added in core of NHibernate, so it is preferable (but of course not necessary) to get familiar with it.

Just can’t allow myself to forget about some political issues with ConfOrm and Fluent NHibernate :). ConfOrm project was started by Fabio Maulo who is lead of NHibernate project (correct me here if I’m wrong). And 3.2 version of NHibernate was released with mapping in code part that basically was very similar to ConfOrm way of doing things.

This fact has raised a little storm in twitter and James Gregory (author of Fluent NHibernate) wrote a blog post to explain what he thinks about it.

Some time later Fabio wrote a response post where he has shown how you can reuse your Fluent mappings with new API :).

So, don’t where it will end, but politics in open source space also takes place :). I recommend you to read mentioned two posts, just to be informed.

Now lets get back to our project. First thing we are going to do is add some entities to work with. NHibernate uses POCO objects. It means that you don’t need to inherit from base classes or implement some interfaces in order to create an entity that is going to be managed by NHibernate. Two things required:

  1. Entity should have public/protected default constructor (constructor with no parameters)
  2. All properties and methods should be virtual

So lets create some entities with associations and properties. Here is example domain model I’ve created:

domain model

Here is source code for one of the entities:

using System.Collections.Generic;

namespace nhrevamp.Core
{
    public class Post : Entity
    {
        public Post()
        {
            this.Comments = new HashSet<Comment>();
            this.Tags = new HashSet<Tag>();
        }

        public virtual string Title { get; set; }

        public virtual string Content { get; set; }

        public virtual ICollection<Comment> Comments { get; protected set; }

        public virtual ICollection<Tag> Tags { get; protected set; }
    }
}

All entities inherit from base class Entity with single property Id:

public abstract class Entity
{
    public virtual int Id { get; protected set; }
}

Notice that we are using ICollection from System.Collections.Generic not from Iesi.Collections. The reason for that is to keep our domain model as clean as possible. Also we initialize collections in constructor in order to avoid nasty NullReferenceException’s. And also we mark setters for collections as protected, just to avoid possibility to replace all collection with new one accidently.

So we have:

  1. One to many association (Post has many Comments)
  2. Many to one association (each Comment belongs to one Post)
  3. Many to many association (Post has many Tags and Tag has many Posts)

NHibernate has two main interfaces that you are going to work with. First is ISessionFactory. Instance of it should be used as a singleton and configured only once. This operation will take time, especially for complex domain models. The good news is that ISessionFactory is serializable and are able to cache it in order to not recreate it each time. Second interface is ISession. This one is used to query entities, update and delete them. Creation of ISession object is small, but you should consider some lifetime management issues with ISession. Here I’ve described how you can easily integrate it with MVC. 

In order to create ISessionFactory we need to configure it and provide mappings for our domain model. Lets start with configuration (you can read full list of available options here). Add new class to your .Data project, lets call it NHibernateConfigurator and create a single method there -BuildSessionFactory. Code there should be the following:

public class NHibernateConfigurator
{
    public ISessionFactory BuildSessionFactory()
    {
        var cfg = new Configuration();
        cfg.SessionFactory()
           .Proxy.Through<ProxyFactoryFactory>()
           .Integrate.Using<MsSql2008Dialect>()
           .Connected.ByAppConfing("connectionString");

        return cfg.BuildSessionFactory();
    }
}

So we say that we are going to work with SQL Server 2008 and connection string is placed in connection strings section of application settings file (web.config in our case).

This post is written for NHibernate 3.1 version. And this version has no default proxy factory with it. So you need to execute one more NuGet command for Data project: Install-Package NHibernate.LinFu. 3.2 version will be delivered with default proxy factory.

Now to the mappings. Its so easy, that you even wouldn’t believe:

public class DomainMapper
{
    public HbmMapping GenerateMappings()
    {
        IEnumerable<Type> domainEntities = GetDomainEntities();

        ObjectRelationalMapper relationalMapper = new ObjectRelationalMapper(); 
        relationalMapper.TablePerConcreteClass(domainEntities); // each concrete class should have its own table in DB
        relationalMapper.Patterns.PoidStrategies.Add(new NativePoidPattern()); // primary keys are generated by DB with identity field
        relationalMapper.Patterns.Sets.Add(new UseSetWhenGenericCollectionPattern()); // ICollection when met in classes should use Set in mappings
        relationalMapper.ManyToMany<Post, Tag>(); // Many to many association by some reasons cant be picked by ConfOrm. Need in set it manually
        relationalMapper.Cascade<Post, Tag>(Cascade.Persist); // when post is saved, tag also needs to be saved

        var patternsAppliers = new CoolPatternsAppliersHolder(relationalMapper); // this is set of column naming packs it used to get nice column names in FKs like PostId in Comments table
        patternsAppliers.Merge(new ClassPluralizedTableApplier(new EnglishInflector())); // means that Comment entity will have Comments table in DB
        Mapper mapper = new Mapper(relationalMapper, patternsAppliers);

        HbmMapping mapping = mapper.CompileMappingFor(domainEntities);
        File.WriteAllText(@"D:\mapping.xml", Serialize(mapping));

        return mapping;
    }

    private static IEnumerable<Type> GetDomainEntities()
    {
        Assembly domainAssembly = typeof(Entity).Assembly;
        IEnumerable<Type> domainEntities = from t in domainAssembly.GetTypes()
                                           where t.BaseType == typeof(Entity) && !t.IsGenericType
                                           select t;
        return domainEntities;
    }

    /// <summary>
    /// Generates XML string from <see cref="NHibernate"/> mappings. Used just to verify what was generated by ConfOrm to make sure everything is correct.
    /// </summary>
    protected static string Serialize(HbmMapping hbmElement)
    {
        var setting = new XmlWriterSettings { Indent = true };
        var serializer = new XmlSerializer(typeof(HbmMapping));
        using (var memStream = new MemoryStream())
        {
            using (var xmlWriter = XmlWriter.Create(memStream, setting))
            {
                serializer.Serialize(xmlWriter, hbmElement);
                memStream.Flush();
                byte[] streamContents = memStream.ToArray();

                string result = Encoding.UTF8.GetString(streamContents);
                return result;
            }
        }
    }
}

This code block contains one utility method called Serialize. It is used just to verify mappings. You can skip it. But its useful. That’s all. Some details I’ve added in comments. So now we are ready to start working with NHibernate.

Now we need provide generated mappings for our ISessionFactory. So add next two lines to the BuildSessionFactory method of NHibernateConfiguratorClass:

HbmMapping generateMappings = new DomainMapper().GenerateMappings();
cfg.AddDeserializedMapping(generateMappings, "domain");

Now we are ready to use NHibernate. First thing we need is actually DB schema. We can generate it from mappings with the help of SchemaExport class:

new SchemaExport(cfg).Execute(true, true, false);

This command is executed in NHibernateConfigurator class and creates all required tables for us:

Data base schema

In order to work properly NHibernate requires transactions to wrap all queries. I’ve described asp.net mvc integration in previous post. So I won’t describe it here.

The last thing you need to see here is a way to work with data. Here is how we can save new blog with post and some comments:

ISessionFactory sessionFactory = new NHibernateConfigurator().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction transaction = session.BeginTransaction())
    {
        Post post = new Post
                        {
                            Content = "test"
                        };
        post.Tags.Add(new Tag
                          {
                              Name = "test"
                          });
        post.Comments.Add(new Comment
                              {
                                  Author = "me",
                                  Content = "NH is awesome",
                                  Post = post
                              });
        session.SaveOrUpdate(post);
        transaction.Commit();
    }
}

Notice that we save only Post object, all associations are going to be saved by cascade. Generated SQL is straight forward:

begin transaction with isolation level: Unspecified

INSERT INTO Posts
           (Title, Content)
VALUES     (NULL /* @p0 */,
            'test' /* @p1 */)
select SCOPE_IDENTITY()

INSERT INTO Comments
           (Author, Content, PostId)
VALUES     ('me' /* @p0 */,
            'NH is awesome' /* @p1 */,
            1 /* @p2 */)
select SCOPE_IDENTITY()

INSERT INTO Tags
           (Name)
VALUES     ('test' /* @p0 */)

select SCOPE_IDENTITY()

INSERT INTO PostToTag
           (PostId,
            TagId)
VALUES     (1 /* @p0 */,
            1 /* @p1 */)
commit transaction

NHibernate has mature Querying API that was improved in 3.0 version. Also it has LINQ implemented with session.Query<T> extension method. This post has no intention do describe them.

So you are almost NHibernate Guru already ;). What to read next:

  • Overriding GetHashCode and Equals methods for your domain entities (link)
  • Primary keys generations and consequences of using them (link)
  • Lazy, eager loading (link) and select N+1 problem (link)
  • Transactions and Sessions lifetime management (link)
  • Inverse attribute for mapping collections (link)

Happy NHibernating!

Apr 12, 2011

Unit testing classes with a lot of dependencies

I’m sure every TD developer will scream that it’s not right to have classes with a lot of dependencies. I agree with you, but it happens. It happens for example in MVP pattern for ASP.NET, or for controllers in MVC.

Why it happens? The main reason I think are unnecessary abstractions. Many applications have interface like IRepository<T> : where T : IEntity. Such interface seams to be very useful. It gives you strongly typed access to the entities, and gives you ability to put common methods there (like Get<T>(int id)). Everything looks good so far. We configure our application to use IoC container and don’t bother with dependencies:

public ProductsController : Controller
{
    private readonly IRepository<Product> productsRepository;

    public ProductsController(IRepository<Product> productsRepository)
    {
        this.productsRepository = productsRepository;
    }

    public ActionResult Index()
    {
        var products = productsRepository.GetAll();
        return View(products);
    }
}

Everything looks good so far and we are able to write very simple unit test for it. Its easy to mock GetAll() method and verify that View.Model contains exact the same collection that returned from repository.

But then you need to create a Create method that requires getting list of all categories that could be assigned to product. And all of a sudden you have two dependencies:

public ProductsController : Controller
{
    private readonly IRepository<Product> productsRepository;
    private readonly IRepository<Category> categoriesRepository;

    public ProductsController(IRepository<Product> productsRepository, IRepository<Category> categoriesRepository)
    {
        this.productsRepository = productsRepository;
        this.categoriesRepository = categoriesRepository;
    }

    public ActionResult Index()
    {
        var products = productsRepository.GetAll();
        return View(products);
    }

    public ActionResult Create()
    {
        var categories = categoriesRepository.GetAll();
        ViewBag.Categories = categories;
        return View();
    }
}

Its still looking good. But only if you have 2-3 tests that are using ProductsController constructor with 1 parameter. When you have 20 of those its becoming a nightmare to add new dependency in constructor.

I do understand that its not best example of why a lot of dependencies happens, but its real one. Its very easy to have up to 4-6 decencies in constructor. And to do with it in tests? Each test needs to set 2 or 3 of them and he doesn’t cares about other. My first approach was creating a helper methods as such:

public ProductsController GetController(IRepository<Product> productsRepository)
{
    return new ProductsController(productsRepository, Mock.Of<IRepository<Category>>);
}

Its perfectly works for classes with less then 3 dependencies. But even there the problem still exists. Consider mocking of current HttpContext.Current.User.Identity. It may happen that each controller action needs access to it, but most of tests doesn’t care what is going to be returned as current user. You will need to copy paste mocking code in each of such methods, or put some complex chain of methods calling each other to get default user for all test controllers.

What I prefer to do now is having a simple factory for controllers (presenters) in test class:

internal class ProductsControllerFactory()
{
    public ProductsControllerFactory()
    {
        this.CategoriesRepsitory = Mock.Of<IRepository<Category>>();
        this.ProductsRepository = Mock.Of<IRepository<Product>>();
        
        // you can put all default stubs here
    }

    public ProductsController GetController()
    {
        return new ProductsController(this.CategoriesRepository, 
                                      this.ProductsRepository);
    }

    public IRepository<Category> CategoriesRepsitory { get; set; }

    public IRepository<Product> ProductsRepository { get; set; }
}

So you end up with having constructor call in one place. Adding a dependency won’t affect existing tests, it will affect only controller factory. Each test can easily set dependency it needs and ignore dependencies it doesn’t cares about.

Apr 9, 2011

Lightweight NHibernate and ASP.NET MVC integration with Autofac

Many times when new project stars and we want to use NHibernate relatively a lot of work need to be done. Among them are:

  • Mapping of entities (I prefer automapping)
  • ISessionFactory singleton
  • ISession lifetime management (Per web request)
  • Transaction management

Sharp architecture project has all of them done and ready to use. But as for me this project has become too big and hard to understand. I wanted to have full control on what is happening in my app and didn’t want to have such a lot of abstractions. For example Repository and Entity objects that have inheritance chain about to 5 or 6 objects.

So I decided to show how very simple integration can be made with a minimum amount of code. To get all mentioned libraries I will use NuGet. We will need:

  • NHibernate
  • Fluent NHibernate
  • Autofac
  • Autofac.Mvc3

Lets start with mapping / session factory configuration:

public Configuration Configure()
{
    var configuration = new Configuration();
    configuration.SessionFactory()
                 .Proxy.Through<ProxyFactoryFactory>()
                 .Integrate.Using<MsSql2005Dialect>()
                 .Connected.ByAppConfing("dbConnection");


    FluentConfiguration fluentConfiguration = Fluently.Configure(configuration);
    fluentConfiguration.Mappings(map => map.AutoMappings.Add(
                                            new ModelGenerator().Generate()));

    return fluentConfiguration.BuildConfiguration();
}

public ISessionFactory GetSessionFactory()
{
    var configuration = Configure(); 
    return configuration.BuildSessionFactory();
}

Few things to note here. Combination of Loquacious and Fluent configuration is used because first one is supporting all NHibernate features, second one handles mappings integration. Also Model generator class is used:

private class ModelGenerator
{
    public AutoPersistenceModel Generate()
    {
        AutoPersistenceModel automap = new AutoPersistenceModel();

        automap.Conventions.AddFromAssemblyOf<ModelGenerator>();
        automap.UseOverridesFromAssemblyOf<ModelGenerator>();
        automap.AddEntityAssembly(Assembly.GetAssembly(typeof (Entity)))
            .Where(objectType => objectType.IsSubclassOf(typeof(Entity)));

        return automap;
    }
}

Here we setup location for the conventions, overriding's and entities. All classes that are inherited from Entity will be mapped. For conventions I’m using sharp architecture’s with small tweaks to have nice constraints names when generating schema from mappings:

public class ReferenceConvention : IReferenceConvention
{
    public void Apply(FluentNHibernate.Conventions.Instances.IManyToOneInstance instance)
    {
        string fkName = string.Format("{0}_{1}_FK", 
                                      instance.Name, instance.EntityType.Name);
        instance.ForeignKey(fkName);

        instance.Column(instance.Property.Name + "Fk");
    }
}

public class HasManyToManyConvention : IHasManyToManyConvention
{
    public void Apply(IManyToManyCollectionInstance instance)
    {
        string fkName = string.Format("{0}_{1}_FK", 
                                      instance.Member.Name, instance.EntityType.Name);
        instance.Key.ForeignKey(fkName);

        instance.Cascade.SaveUpdate();
    }
}

Now to the web part. In global asax on Application_Start event we need to setup Autofac and change the default controllers factory. To do this:

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetAssembly(typeof (AuthorizationController)));
builder.Register(x => new NHibernateConfigurator().GetSessionFactory())
    .SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession())
    .InstancePerHttpRequest();

builder.RegisterModule(new AutofacWebTypesModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Code here is pretty clear. We setup ISessionFactory to be singleton, ISession instance is resolved by container and has PerHttpRequest lifestyle. Notice call of builder.RegisterModule that is going to add all the required http modules to support per web request lifestyle and change default controller factory to the one that uses Autofac. So now we are able to write code like this:

public class AuthorizationController : Controller
{
      private ISession session;

      public AuthorizationController(ISession session)
      {
          this.session = session;
      }

      public ActionResult Index()
      {
          var users = this.session.QueryOver<User>().List();
          return View(users);
      }
}

So we have controller that depends on ISession, which depends on ISessionFactory, which depends on our Nhibernate configurator class. Isn’t it kind from Autofac to handle all this? Smile

One last but important thing we need to do. Each call to the data base should be wrapped to correct transaction. You can read here why. The easiest way to handle this is to create action filter:

public class TransactionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        DependencyResolver.Current.GetService<ISession>().BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ITransaction currentTransaction = DependencyResolver.Current.GetService<ISession>().Transaction;

        if (currentTransaction.IsActive)
        {
            if (filterContext.Exception != null && filterContext.ExceptionHandled)
            {
                currentTransaction.Rollback();
            }
        }
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        ITransaction currentTransaction = DependencyResolver.Current.GetService<ISession>().Transaction;

        base.OnResultExecuted(filterContext);
        try
        {
            if (currentTransaction.IsActive)
            {
                if (filterContext.Exception != null && !filterContext.ExceptionHandled)
                {
                    currentTransaction.Rollback();
                }
                else
                {
                    currentTransaction.Commit();
                }
            }
        }
        finally
        {
            currentTransaction.Dispose();
        }
    }
}

Original implementation is taken from Sharp architecture and small changes made due to Autofac. So now out Index method should be marked with transaction attribute:

[Transaction]
public ActionResult Index()
{
    return View();
}

That's probably all we need to have NHibernate. As always source code is attached:

Jan 6, 2011

Episerver CMS 6 search

Had to make some additional staff in EPiServer search functionality. I had to add ability to filter pages by category, page type, and keyword in content. Firstly I have tried to do it with DataFactory.Instance.FindPagesWithCriteria method. But the thing is that I couldn’t  find a way to filter data by search keyword.

I knew that SearchDataSource does this somehow and wanted to reuse that logic. But when I looked at it in reflector, I found a method 100 lines long doing some really fancy staff to make select by keywords. So the best way to make search that I need is to do it through SearchDataSource.

Fortunately it provides public property called Criteria. It is a criteria that are going to be passed for underlying DataFactory.FindPagesWithCriteria call.

So the search that I needed could be implemented in the this way. Aspx part:

<EPiServer:SearchDataSource ID="uiSearchDataSource" runat="server" EnableVisibleInMenu="false"
                            PageLink="<%# PageReference.StartPage %>">
    <SelectParameters>
        <asp:QueryStringParameter Name="SearchQuery" QueryStringField="search" DefaultValue="" />
    </SelectParameters>
</EPiServer:SearchDataSource>

And in code behind:

var pageTypeCategory = new PropertyCriteriaControl(new PropertyCriteria
                            {
                                Condition = CompareCondition.Equal,
                                Name = "PageTypeID",
                                Type = PropertyDataType.PageType,
                                Value = PageType.Load("Article").ID.ToString(),
                                Required = true
                            });

var pageTypeCategory1 = new PropertyCriteriaControl(new PropertyCriteria
                            {
                                Condition = CompareCondition.Equal,
                                Name = "PageCategory",
                                Type = PropertyDataType.Category,
                                Value = Category.Find("category2").ID.ToString(),
                                Required = true
                            });

this.uiSearchDataSource.Criteria.Add(pageTypeCategory);
this.uiSearchDataSource.Criteria.Add(pageTypeCategory1);

Note that Name property of each criteria should be as shown in code above, otherwise it won’t work. Hope it helps someone!

Nov 29, 2010

TFS for the SVN user

Originally I wanted to name this post as Making your life a little bit easier with all TFS horror and then decided to change it. The reason for changing title is that my irritation on TFS was called only by VisualSVN usability. I spoke with people who are using TFS for long period and have never used any other tools and they say that it is really good and everything is just obvious. Obvious for them, but not for me.

Currently I have no choice except using TFS as a source control system.  Previously I used Subversion with VisualSVN add-in to integrate with visual studio.

The only way for me not to go crazy while doing really simple tasks with TFS (like commit, merging) was making some configurations. Maybe some tips will save someone's time. So lets start with them one by one.

Merging tool

First of all when you merge conflicts with build in merging tool you really won’t understand what has changed. Changes are shown only in rows. So if one symbol is change you will need to hunt it in entire row by yourself. Also it is hard for me to see where conflict was resolved successfully with no need for me to do something and where my assistance is required.

Now I’m using WinMerge tool. Its also not the best, but really better then default one. To configure it you need to go to the Tools->Options->Source Control->Visual Studio Team Foundation Server and click Configure User Tools button. Click Add… button to add new command.

User tool configuration window

Select Compare operation, provide to WinMerge and fill arguments with this value: /ub /dl %6 /dr %7 %1 %2.

Click ok and add another new command select Merge, provide WinMerge path and fill arguments: /ub /dl %6 /dr %7 %1 %2 %4. Click Ok.

Here is a post where described how to configure TFS with other tools.

Compare on double click

Another really annoying thing is that when you are about to commit all your changes and you double click on a file it is just opened (in Notepad as I rememer O_O). Why would anyone need to see his pending change file in notepad? To compare it with server version you need to click on special buttons:

Checkin pending changes dialog

I didn’t want to pixel hunt that buttons. I wanted to compare with latest version on double mouse click. The good news that it is possible with TFS. How to configure it you can read here (btw the only option that worked for me is with registry and only after reboot).

Ghost changes

My favourite trick with TFS is just go to WebForm1.aspx press space somewhere and hit ctrl+z. You even didn’t hit save. Then you can open pending changes dialog and there real surprise is waiting for you. TFS will say that you have 3 pending changes Open-mouthed smile. Wow, when I saw this for the first time I couldn’t believe my eyes!

Ofcourse  when you click Check In button it will check real changes in the file and won’t commit file with empty changes. But I used to look through all changes that I’m going to commit and don’t want to hunt for really changed files among rest of them.

To solve this TFS power tools can be used. They contain a lot of useful features and one of them is TFPT.EXE tool. It is command line utility and can do a lot of stuff that you usually do with interface. And guess what? This tool has a special command to roll back unchanged files.

I added this tool as an external tool. To do this you can do the following go to the Tools->External Tools and click Add button. There you need to fill all the fields like this:

external tools configuration

I named the command as undo. You can name it the way you want. After you do it in Tools menu new option will be added:

undo

When clicked following output will be shown for me:

undo results

Auto merge

Another reason why you would want to install power tools is auto merge all button.

automerge all

The thing is: when you update, even if TFS is able to merge changes by himself it will force you to hit auto merge, auto merge, auto merge on each conflicted file. With this button you can do it in one place for all files. If somebody knows how to force it auto merge when possible without me clicking something I would really appreciate your help.

Remembering credentials

It won’t be an issue for the most of the TFS users, but it was for me.

Our TFS server is located in a different active directory domain. And each time you open a solution it asks you for the credentials and has no option to save them. I found this question on the msdn. The solution that worked for me is:

  1. Open start menu and in the quick search find for “manage network passwords” (in Russian version of windows you need to look for “управление сетевыми паролями”)
  2. In the opened window click on Add a Windows credential
  3. Fill all the required fields and click ok (server name should be provided with no http or something else, just name)

After doing this Visual Studio won’t ask password.

Unshelve with merge

I didn’t really used this feature of power tools yet. But as I was told default unshelving functionality will just replace all the files in your working copy. And if time has passed since you shelved all changes will be lost. Power tools allows you to merge changes and not just override.

So I think that those are all the configurations that I have made for today. It I remember something else I’ll write a new post.