Click here to Skip to main content
15,885,546 members
Articles / DevOps / TFS
Tip/Trick

TFS: Compare Changeset in ASP.NET C#

Rate me:
Please Sign up or sign in to vote.
3.00/5 (1 vote)
16 Feb 2016CPOL 11.1K   5  
How to compare the latest version with the previous version in C#

Introduction

In this post, I am going to demonstrate comparing changeset in C#. I will cover the following topics:

  1. Get history (list of all changeset)
  2. Download and compare files

For comparing two files, we use Winmerge.

TFS Demo

Take reference of the below DLLs.

DLL

HTML
<table width="100%">
    <tr>
      <td>
        <asp:Literal ID="litTfsParentFolderPath" runat="server"
        Text="TFS Parent Folder Path"></asp:Literal></td>
      <td>
        <asp:TextBox ID="txtTfsParentFolderPath" runat="server"
        Text="$/HBE/HBE/DEV1/Source/Business/Eligibility/*"
        Enabled="false" Width="400px"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>
        <asp:Literal ID="litChildFolderName" runat="server"
        Text="TFS Child Folder Name"></asp:Literal></td>
      <td>
        <asp:DropDownList ID="ddlChildFolders" runat="server"
        Width="410px" OnSelectedIndexChanged="ddlChildFolders_SelectedIndexChanged"
        AutoPostBack="true"></asp:DropDownList>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <asp:GridView ID="grvChangeSetData" runat="server"
        AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333"
          GridLines="None" OnRowDataBound="grvChangeSetData_RowDataBound"
          OnRowCommand="grvChangeSetData_RowCommand">
          <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
          <Columns>
            <asp:TemplateField HeaderText="Changeset Number"
            HeaderStyle-Width="10%" ItemStyle-Width="10%"
            ItemStyle-VerticalAlign="Top">
              <ItemTemplate>
                <asp:Literal ID="litChangeSetNo" runat="server"
                Text='<%#Bind("ChangeSetNumber") %>'> </asp:Literal>
              </ItemTemplate>
              <HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
              <ItemStyle VerticalAlign="Top" Width="10%"></ItemStyle>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Owner" HeaderStyle-Width="10%"
            ItemStyle-Width="10%" ItemStyle-VerticalAlign="Top">
              <ItemTemplate>
                <asp:Literal ID="litOwnerDisplayName" runat="server"
                Text='<%#Bind("OwnerDisplayName") %>'> </asp:Literal>
              </ItemTemplate>
              <HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
              <ItemStyle VerticalAlign="Top" Width="10%"></ItemStyle>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Created Date" HeaderStyle-Width="10%"
            ItemStyle-Width="10%" ItemStyle-VerticalAlign="Top">
              <ItemTemplate>
                <asp:Literal ID="litCreateDate" runat="server"
                Text='<%#Bind("CreateDate") %>'> </asp:Literal>
              </ItemTemplate>
              <HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
              <ItemStyle VerticalAlign="Top" Width="10%"></ItemStyle>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Comment" HeaderStyle-Width="10%"
            ItemStyle-Width="10%" ItemStyle-VerticalAlign="Top">
              <ItemTemplate>
                <asp:Literal ID="litComment" runat="server"
                Text='<%#Bind("Comments") %>'> </asp:Literal>
              </ItemTemplate>
              <HeaderStyle HorizontalAlign="Center" Width="10%"></HeaderStyle>
              <ItemStyle VerticalAlign="Top" Width="10%"></ItemStyle>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Files" HeaderStyle-Width="10%"
            ItemStyle-Width="10%" ItemStyle-VerticalAlign="Top">
              <ItemTemplate>
                <asp:Repeater ID="rpFiles" runat="server"
                OnItemCommand="rpFiles_ItemCommand">
                  <HeaderTemplate>
                    <table width="100%">
                  </HeaderTemplate>
                  <ItemTemplate>
                    <tr>
                      <td>
                        <asp:LinkButton ID="lnkFileName" runat="server"
                        Text='<%# Bind("FileName") %>'
                          CommandName="DownloadFile" CommandArgument='<%# Bind
                          ("CommandArgument") %>'></asp:LinkButton>
                        <asp:LinkButton ID="lnkCompare"
                        runat="server" Text="Compare"
                          CommandName="CompareFile" CommandArgument='<%# Bind
                          ("CommandArgument") %>'></asp:LinkButton>
                      </td>
                    </tr>
                  </ItemTemplate>
                  <FooterTemplate>
                    </table>
                  </FooterTemplate>
                </asp:Repeater>
              </ItemTemplate>
              <HeaderStyle HorizontalAlign="Center"
              Width="10%"></HeaderStyle>
              <ItemStyle VerticalAlign="Top"
              Width="10%"></ItemStyle>
            </asp:TemplateField>
          </Columns>
          <EditRowStyle BackColor="#999999" />
          <FooterStyle BackColor="#5D7B9D"
          Font-Bold="True" ForeColor="White" />
          <HeaderStyle BackColor="#5D7B9D"
          Font-Bold="True" ForeColor="White" />
          <PagerStyle BackColor="#284775"
          ForeColor="White" HorizontalAlign="Center" />
          <RowStyle BackColor="#F7F6F3"
          ForeColor="#333333" />
          <SelectedRowStyle BackColor="#E2DED6"
          Font-Bold="True" ForeColor="#333333" />
          <SortedAscendingCellStyle BackColor="#E9E7E2" />
          <SortedAscendingHeaderStyle BackColor="#506C8C" />
          <SortedDescendingCellStyle BackColor="#FFFDF8" />
          <SortedDescendingHeaderStyle BackColor="#6F8DAE" />
        </asp:GridView>
      </td>
    </tr>
  </table>

Put the below code in .cs file:

C#
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.VersionControl.Client;
C#
namespace TFSDemo
{
  public partial class _Default : Page
  {
    #region Properties
    public TfsTeamProjectCollection teamProjectCollection
    {
      get { return GetTFS(); }
    }
    public string GetTFSPath
    {
      get { return ConfigurationManager.AppSettings["URI"]; }
    }
    public string GetUser
    {
      get { return ConfigurationManager.AppSettings["User"]; }
    }
    public string GetPassword
    {
      get { return ConfigurationManager.AppSettings["Password"]; }
    }
    public string GetDomain
    {
      get { return ConfigurationManager.AppSettings["Domain"]; }
    }
    #endregion
    #region PageLoad
    protected void Page_Load(object sender, EventArgs e)
    {
      if (!IsPostBack)
      {
        BindSubFolders();
      }
    }
    #endregion
    #region Events

    protected void ddlChildFolders_SelectedIndexChanged(object sender, EventArgs e)
    {
      try
      {
        string filePath = ddlChildFolders.SelectedItem.Value.ToStringSafe();
        List<SubFolderChangeSet> listChangeSet = GetChangeSetBySubFolderName(filePath);
        grvChangeSetData.DataSource = listChangeSet.Distinct().Select(x => x);
        grvChangeSetData.DataBind();
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }
    protected void grvChangeSetData_RowDataBound(object sender, GridViewRowEventArgs e)
    {
      if (e.Row.RowType == DataControlRowType.DataRow)
      {
        Repeater rpFiles = e.Row.FindControl("rpFiles") as Repeater;
        if (rpFiles != null)
        {
          rpFiles.ItemCommand += new RepeaterCommandEventHandler(rpFiles_ItemCommand);
          List<Change> listChangeset = ((e.Row.DataItem) as SubFolderChangeSet).listChange;
          List<FileNames> listFileName = new List<FileNames>();
          if (listChangeset != null && listChangeset.Count > 0)
          {
            foreach (Change change in listChangeset)
            {
              FileNames file = new FileNames();
              file.ChangeSetNumber = ((e.Row.DataItem) as SubFolderChangeSet).ChangeSetNumber;
              file.FileName = change.Item.ServerItem.Substring
              (change.Item.ServerItem.LastIndexOf('/') + 1);
              file.CommandArgument = file.ChangeSetNumber + "@" + file.FileName;
              listFileName.Add(file);
            }
            rpFiles.DataSource = listFileName;
            rpFiles.DataBind();
          }
        }
      }
    }
    protected void rpFiles_ItemCommand(object source, RepeaterCommandEventArgs e)
    {
      if (e.CommandName.Equals("DownloadFile", StringComparison.OrdinalIgnoreCase))
      {
        string[] args = e.CommandArgument.ToStringSafe().Split('@');
        if (args != null && args.Length > 0)
        {
          int changesetId = args[0].ToIntSafe();
          VersionControlServer vcs = GetVersionServer(teamProjectCollection);
          if (vcs != null)
          {
            Changeset cs = vcs.GetChangeset(changesetId);
            foreach (Change ch in cs.Changes)
            {
              string filename = ch.Item.ServerItem.Substring
              (ch.Item.ServerItem.LastIndexOf('/') + 1);
              if (filename.Equals(args[1].ToStringSafe(), StringComparison.OrdinalIgnoreCase))
              {
                ch.Item.DownloadFile(System.IO.Path.GetTempPath() +
                           ch.Item.ChangesetId +
                           ch.Item.ServerItem.Split('/')[
                             ch.Item.ServerItem.Split('/').Length - 1]);
              }
            }
          }
        }
      }
      if (e.CommandName.Equals("CompareFile", StringComparison.OrdinalIgnoreCase))
      {
        string[] args = e.CommandArgument.ToStringSafe().Split('@');
        if (args != null && args.Length > 0)
        {
          int changesetId = args[0].ToIntSafe();
          VersionControlServer vcs = GetVersionServer(teamProjectCollection);
          if (vcs != null)
          {
            Changeset cs = vcs.GetChangeset(changesetId);
            string matchFile = string.Empty;
            string filePath = string.Empty;
            filePath = System.IO.Path.GetTempPath();
            //filePath = Server.MapPath("~//TFSFiles");
            foreach (Change ch in cs.Changes)
            {
              string filename = ch.Item.ServerItem.Substring
              (ch.Item.ServerItem.LastIndexOf('/') + 1);
              if (filename.Equals(args[1].ToStringSafe(), StringComparison.OrdinalIgnoreCase))
              {
                matchFile = ch.Item.ServerItem.ToStringSafe();
                ch.Item.DownloadFile(filePath +
                           ch.Item.ChangesetId +
                           ch.Item.ServerItem.Split('/')[
                             ch.Item.ServerItem.Split('/').Length - 1]);
              }
            }
            if (!string.IsNullOrWhiteSpace(matchFile))
            {
              Item item = vcs.GetItem(matchFile);
              item.DownloadFile(filePath + changesetId + "-New-" +
              matchFile.Split('/')[matchFile.Split('/').Length - 1]);
              var winmerge = Process.Start(@"C:\Program Files (x86)\WinMerge\WinMergeU.exe",
                        String.Format("{0}{1} {0}{2}", filePath,
                               @"\" + changesetId + matchFile.Substring
                               (matchFile.LastIndexOf('/') + 1),
                               @"\" + changesetId + "-New-" +
                               matchFile.Substring(matchFile.LastIndexOf('/') + 1)));
            }
          }
        }
      }
    }
    protected void grvChangeSetData_RowCommand(object sender, GridViewCommandEventArgs e)
    {
    }
    #endregion
    #region PrivateMethods
    private TfsTeamProjectCollection GetTFS()
    {
      TfsTeamProjectCollection tpc = null;
      try
      {
        Uri tfsUri = new Uri(GetTFSPath);
        TfsConfigurationServer configurationServer =
        TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
        configurationServer.Credentials = new NetworkCredential(GetUser, GetPassword, GetDomain);
        configurationServer.Authenticate();
        ReadOnlyCollection<CatalogNode> collectionNodes =
        configurationServer.CatalogNode.QueryChildren(new[]
        { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);
        foreach (CatalogNode collectionNode in collectionNodes)
        {
          Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
          tpc = configurationServer.GetTeamProjectCollection(collectionId);
        }
      }
      catch (Exception ex)
      {
        throw ex;
      }
      return tpc;
    }
    private VersionControlServer GetVersionServer(TfsTeamProjectCollection teamProjectCollection)
    {
      return teamProjectCollection.GetService<VersionControlServer>();
    }
    private void BindSubFolders()
    {
      try
      {
        if (teamProjectCollection != null)
        {
          VersionControlServer vcs = GetVersionServer(teamProjectCollection);
          var subFolders = vcs.GetItems(txtTfsParentFolderPath.Text.ToStringSafe());
          List<string> listSubFolders = new List<string>();
          foreach (var item in subFolders.Items)
          {
            listSubFolders.Add(item.ServerItem);
          }
          ddlChildFolders.DataSource = listSubFolders;
          ddlChildFolders.DataBind();
        }
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }
    private List<SubFolderChangeSet> GetChangeSetBySubFolderName(string filePath)
    {
      List<SubFolderChangeSet> listChangeset = new List<SubFolderChangeSet>();
      try
      {
        var vsStore = teamProjectCollection.GetService<VersionControlServer>();

        var histories =
            vsStore.QueryHistory(
                filePath,
                VersionSpec.Latest, default(int),
                RecursionType.Full, null, null, null, Int32.MaxValue, true, false, true);
        foreach (Changeset history in histories)
        {
          SubFolderChangeSet sbfChangeSet = new SubFolderChangeSet();
          sbfChangeSet.ChangeSetNumber = history.ChangesetId;
          sbfChangeSet.Owner = history.Owner;
          sbfChangeSet.OwnerDisplayName = history.OwnerDisplayName;
          sbfChangeSet.Comments = history.Comment;
          listChangeset.Add(sbfChangeSet);
          sbfChangeSet.listChange = new List<Change>();
          sbfChangeSet.listChange.AddRange(history.Changes);
          foreach (Change change in history.Changes)
          {
            sbfChangeSet.CreateDate = change.Item.CheckinDate;
          }
        }
      }
      catch (Exception ex)
      {
        throw ex;
      }
      return listChangeset;
    }
    #endregion
  }
  #region Classes
  public class SubFolderChangeSet
  {
    public int ChangeSetNumber { get; set; }
    public string Owner { get; set; }
    public string OwnerDisplayName { get; set; }
    public string Comments { get; set; }
    public DateTime CreateDate { get; set; }
    public List<Change> listChange { get; set; }
  }
  public class FileNames
  {
    public int ChangeSetNumber { get; set; }
    public string FileName { get; set; }
    public string CommandArgument { get; set; }
  }
  #endregion
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --