Welcome to MSDN Blogs Sign in | Join | Help

ASP.NET Rich Text Editor Control Released to Codeplex

I am glad to announce the release of ASP.NET Rich Text Editor control, that I have blogged about earlier, to the community.

  1. Get the sources for this control from codeplex
  2. Live Demo

Initially was planning to write a lengthy blog entry, but Kirti, my colleague at Microsoft has already written an excellent intro for this so please read more here

Posted by kannans | 3 Comments

Iterators

Going through the documentation I found it hard to figure out how I could expose my custom Enumerator to foreach. I was trying to implement an “Inorder” traversal as a property to my Binary Search Tree, so that I could do the following.

 

BinarySearchTree<int> bst = new BinarySearchTree<int>();

 

      bst.Add(150);

      bst.Add(50);

      bst.Add(175);

      bst.Add(5);

      bst.Add(55);

 

      foreach (int i in bst.InOrder)

            {

                   //Process elements here in Order.

            }

 

            Here is one to way to implement it. Implement a nested type InOrderCollection derived from IEnumerable<T> in your BinarySearchTree class.

 

        public struct InOrderCollection : IEnumerable<T>

        {

            readonly BinarySearchTree<T> bst;

 

            internal InOrderCollection(BinarySearchTree<T> pBst)

            {

                bst = pBst;

            }

 

            IEnumerator<T> IEnumerable<T>.GetEnumerator()

            {

                return new InOrderEnumerator<T>(bst);

            }

 

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

            {

                return new InOrderEnumerator<T>(bst);

            }

 

        }

 

      Now you can add the following property to your BinarySearchTree.

 

  public IEnumerable<T> InOrder

        {

            get

            {

                return new InOrderCollection(this);

            }

        }

 

I realized this could be a generic sample in case you want to expose your collection’s Enumerators to foreach.

 

            [This code snippet is provided under the Microsoft Permissive License.]   

Posted by kannans | 0 Comments

TFS Reporting Simplified

In my last post we saw how to write a TFS Data Source Component. In this one I will explain how to use them to generate a TFS report like the one below leveraging existing ASP.NET controls.

1.       First create a new ASP.NET page.

 

2.       Second register the TFS Data Source component DLL that we built earlier with the following line

 

  <%@ Register TagPrefix="Tfs" Namespace="TfsWebComponents" Assembly="TfsWebComponents" %>

 

3.       Third we need to define a TFS Data Source for our report. So include the following snippet

 

<Tfs:TfsDataSource id="srcWorkItems" Runat="Server" SelectMethod="GetWorkItemsByQuery">

<SelectParameters>

<asp:Parameter Name="teamProjectName" Type="String" DefaultValue="Developer Solutions" Direction="Input"/>

<asp:Parameter Name="storedQueryName" Type="String" DefaultValue="kannans" Direction="Input" />

</SelectParameters>

</Tfs:TfsDataSource>

 

      Note that I have specified SelectMethod="GetWorkItemsByQuery"  which is the name of the method we exposed as public in TFS Data Source Component we saw in my earlier post. The asp:Parameter in above snippet passes the parameters to that method.

 

4.       Fourth, comes the fun part of creating the report. Simply use the existing ASP Grid View control.  I have given the full snippet below.

 

[This code snippet is provided under the Microsoft Permissive License.]

 

 

<%@ Register TagPrefix="Tfs" Namespace="TfsWebComponents" Assembly="TfsWebComponents" %>

 

<asp:Content ID="Content1" ContentPlaceHolderID="Content" Runat="Server">

 

<div style="margin-left:32px; margin-top:32px">

  <asp:GridView

     ID="tfsWorkItems"

     DataSourceID="srcWorkItems"

     AllowSorting="true"

     AutoGenerateColumns="false"

     HeaderStyle-CssClass="WitHeader"

     FooterStyle-CssClass="WitHeader"

     GridLines="Both"

     CellPadding="4"

     RowStyle-CssClass="Wit"

     runat="server" OnRowDataBound="tfsWorkItems_RowDataBound">

     <Columns>   

           <asp:BoundField

                DataField="Priority" HeaderText="Priority"/>  

             <asp:HyperLinkField DataNavigateUrlFields="Id"

                    HeaderText="Id"

                    DataNavigateUrlFormatString="http://YourTFSServer:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker={0}"

                    DataTextField="Id"

                    NavigateUrl="http://YourTfsServer:8080/WorkItemTracking/WorkItem.aspx" />

            <asp:BoundField

                DataField="State" HeaderText="Status"/>  

            <asp:BoundField

                DataField="Title" HeaderText="Title"/>

            <asp:BoundField

                DataField="RemainingWork" HeaderText="Estimate"/>  

            <asp:BoundField

                DataField="ChangedBy"  HeaderText="Updated By"/>

            <asp:BoundField

                DataField="ChangedDate"  HeaderText="Updated On" />

            <asp:BoundField

                DataField="CreatedBy" HeaderText="Opened By"/>

        </Columns>

      </asp:GridView>

    

     <Tfs:TfsDataSource id="srcWorkItems" Runat="Server" SelectMethod="GetWorkItemsByQuery">

     <SelectParameters>

      <asp:Parameter Name="teamProjectName" Type="String" DefaultValue="Developer Solutions" Direction="Input"/>

      <asp:Parameter Name="storedQueryName" Type="String" DefaultValue="kannans" Direction="Input" />

     </SelectParameters>

     </Tfs:TfsDataSource>

 </div>

</asp:Content>

 

Remeber to change the 'YourTFSServer' in the above snippet to your actual tfs server name / port.

Another thing to remember is to add the following to your web.config so that the TFS Data Source would pick it up.

<configuration>

<appSettings/>

<connectionStrings>

<add name="TfsServer" connectionString="http://yourTFsServer:8080

</connectionStrings>

To make the report look pretty I have added some CSS and Icons.  Feel free to include them.

CSS

 

.WitHeader

{

    background:#0148B2;

    font-family:Tahoma;

    font-size:8pt;

    font-weight:bold;

    color:White;

}

 

.Wit

{

   background:#EFF3FF;

   font-family:Tahoma;

   font-size:8pt;

   color:#215DC6;

}

Images

 

Based on the Status text you could format the report to display icons instead of text the following way

// Conditional formatting of Status column in the report by replacing the text with an image.

protected void tfsWorkItems_RowDataBound(object sender, GridViewRowEventArgs e)

{

        if (e.Row.RowType == DataControlRowType.DataRow)

        {

            if (e.Row.Cells[2].Text == "Active")

            {

                e.Row.Cells[2].Text = "<img border=0 src='images/RedCross.png'>";

            }

            else if (e.Row.Cells[2].Text == "Resolved")

                e.Row.Cells[2].Text = "<img border=0 src='images/YellowTick.png'>";

            else if (e.Row.Cells[2].Text == "Closed")

                e.Row.Cells[2].Text = "<img border=0 src='images/GreenTick.png'>";

        }

}

[This code snippet is provided under the Microsoft Permissive License.]

As you can find, it’s quite simple to write the report once you have the TFS Data Source Component. The good thing is that you can extend the TFS Data Source Control, by adding additional public methods and then using them in your ASP.NET web page to write different reports / gadgets including a TFS Dashboard for your team. The possibilities are unlimited.

Posted by kannans | 4 Comments

TFS Data Source ASP.NET Control

While learning ASP.NET for developing the RTE for MSDN Forums I had to interact with multiple teams and provide them with status reports on the work items. Some of them were not using TFS yet for that code base. So I wanted a way to easily write a TFS report, send the url to all these teams.

 

Given my earlier TFS background and the capabilities I learnt exist in ASP world thought why not leverage these two and thus began this exercise to write a TFS Data Source ASP.NET control which I can drop into any ASP.NET web page, bind it to any existing ASP.NET controls to create a simple TFS report.

 

 

TFS Data Source ASP.NET Control Snippet [ Build this as a dll ].

 

[This code snippet is provided under the Microsoft Permissive License.]

 

using System;

using System.Collections;

 

using System.Collections.Generic;

using System.Collections.ObjectModel;

 

using System.ComponentModel;

using System.Text;

 

using System.Web.Configuration;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

using Microsoft.TeamFoundation.Client;

using Microsoft.TeamFoundation.WorkItemTracking.Client;

using Microsoft.TeamFoundation.WorkItemTracking;

using Microsoft.TeamFoundation.Server;

using System.Security.Permissions;

 

[assembly: SecurityPermission(SecurityAction.RequestMinimum)]

 

// TFS ASP.NET Controls

namespace TfsWebComponents

{

    /// <summary>

    ///  TFS Data Source Component

    /// </summary>

    [ToolboxData("<{0}:TfsDataSource runat=server></{0}:TfsDataSource>")]

    public class TfsDataSource : ObjectDataSource

    {

        public TfsDataSource()

        {

            this.TypeName = "TfsWebComponents.TfsServer";

        }

 

    }

 

    /// <summary>

    ///  TFS Data Source Component Implementation.

    /// </summary>

    public class TfsServer

    {

        private readonly String tfsServerUrl;

        /// <summary>

        /// Tfs Server

        /// </summary>

        private TeamFoundationServer tfsServer;

        /// <summary>

        /// Tfs Work Item Store

        /// </summary>

        private WorkItemStore tfsWorkItemStore;

 

        /// <summary>

        ///  Project service.

        /// </summary>

        private ICommonStructureService tfsProjectService;

 

        /// <summary>

        /// Security service

        /// </summary>

        private IGroupSecurityService tfsSecurityService;

 

        /// <summary>

        /// Tfs Server

        /// </summary>

        public TfsServer()

        {

            tfsServerUrl = WebConfigurationManager.ConnectionStrings["TfsServer"].ConnectionString;

            tfsServer = TeamFoundationServerFactory.GetServer(tfsServerUrl);

 

            tfsServer.Authenticate();

            tfsProjectService = (ICommonStructureService)tfsServer.GetService(typeof(ICommonStructureService));

            tfsSecurityService = (IGroupSecurityService)tfsServer.GetService(typeof(IGroupSecurityService));

            tfsWorkItemStore = (WorkItemStore)tfsServer.GetService(typeof(WorkItemStore));

        }

 

 

        /// <summary>

        ///  Get Work items for a given team project using the given stored query name.

        /// </summary>

        /// <param name="teamProjectName">Name of the TFS team project</param>

        /// <param name="storedQueryName">Name of the stored query in TFS</param>

        /// <returns>ReadOnlyCollection of WorkItem</returns>

        public ReadOnlyCollection<TfsWorkItem> GetWorkItemsByQuery(string teamProjectName, string storedQueryName)

        {

            Collection<TfsWorkItem> workItems = new Collection<TfsWorkItem>();

            Hashtable h = new Hashtable();

            h.Add("project", teamProjectName);

 

            foreach (StoredQuery sq in tfsWorkItemStore.Projects[teamProjectName].StoredQueries)

            {

                if (string.Compare(sq.Name,

                                   storedQueryName,

                                   true,

                                   System.Globalization.CultureInfo.CurrentCulture) == 0)

                {

                    WorkItemCollection myWitems = tfsWorkItemStore.Query(sq.QueryText, h);

                    workItems = this.GetWorkItems(myWitems);

                    break;

                }

            }

 

            h = null;

            return new ReadOnlyCollection<TfsWorkItem>(workItems);

        }

 

        /// <summary>

        ///  Get collection of TfsWorkItem given the original WorkItemCollection from TFS.

        /// </summary>

        /// <returns>Collection of TfsWorkItem</returns>

        private Collection<TfsWorkItem> GetWorkItems(WorkItemCollection myWitems)

        {

            Collection<TfsWorkItem> workItems = new Collection<TfsWorkItem>();

 

            foreach (WorkItem itm in myWitems)

            {

                // TfsWorkItem is a wrapper for the real TFS work item

                // It provides get methods to all work Item properties like AssignedTo, State etc.

                TfsWorkItem tfswi = new TfsWorkItem(itm);

 

                //If you want to do additional processing do it here.

 

                workItems.Add(tfswi);

            }

 

            return workItems;

        }

    }

}

 

[This code snippet is provided under the Microsoft Permissive License.]

 

In my next post let’s see how to use this to create a simple nice looking TFS report!

Posted by kannans | 7 Comments

Rich Text Editor for MSDN Forums

It's been a while since I posted. I had been real busy learning all about the web technologies & building a rich text editor for MSDN forums. One version of it is available as a post editor, as part of forums beta server at http://beta.communities.microsoft.com/forums .

In the process I learnt JavaScript, ASP.Net and plan to share my experience in upcoming post including TFS reporting simplified with TFS Data Source ASP.NET Control !.

Posted by kannans | 2 Comments

Creating Cool Icons

Wish you could create those cool vista like icons for your application with ease?. Check out IconWorkshop at http://www.axialis.com/ . I recently tried it out and it looks pretty easy to create those cool icons with this tool.

 

Posted by kannans | 0 Comments
Filed under:

FAQ Item 1: How to generate Md5 hash string for a file.

using System.Security.Cryptography;

....

FileStream file = new FileStream(fileName, FileMode.Open);

MD5 md5 = new MD5CryptoServiceProvider();

byte[] result = md5.ComputeHash(file);

file.Close();

string md5Hash = Convert.ToBase64String(result);

 ....

Posted by kannans | 0 Comments
Filed under:

FREE DOWNLOAD of both standalone Visual Studio Team Foundation clients

FREE DOWNLOAD of both standalone Visual Studio Team Foundation clients to connect to any CodePlex project. Read Koby's entry for details.

http://blogs.msdn.com/korbyp/archive/2006/05/23/605597.aspx 

 

V1.0 Release of Team Foundation Admininstration Tool

I am glad to announce the availability of v1.0 release of the Team Foundation Administration tool at http://go.microsoft.com/fwlink/?LinkId=59385 as a shared source project on www.codeplex.com . To learn more about codeplex check out Jim's blog

First CTP version of Team Foundation Server Admin Tool released!.

The first CTP Version of Team Foundation Server Adminitration Tool has been released today. Its available for download from the GotDotNet .
Posted by kannans | 6 Comments
Filed under:

Mathematics in India of the Vedic age

An interesting article I read on Mathematics in ancient India

 

Posted by kannans | 2 Comments
Filed under:

New Screen Shots of Team Foundation Server User Permission Manager

Last Friday reviewed the proposed screen shots and after going over several iterations finalized on this one

 

Posted by kannans | 1 Comments
Filed under:

Team Foundation Server - User Permission Manager tool

As I mentioned earlier in my Blog entry I am currently working on releasing a CTP version of Team Foundation User Permission Manager tool. Based on our internal use and feedback from users 'not adding users by default to SharePoint and SQL Reporting Services while adding a TFS user' was reported as one of the main pain points. We plan to address this issue with this powertoy tool to help reduce customer pain.

Here is the Main screen shot mock up of the proposed tool

 

Team Foundation Server

 

   “How well is the project going?” is a question too often asked to a first line manager that several of them spend hours to collect the data so that they can present it to their VP or manager.

 

   Quite often organizations end up having one system for requirements, one for tracking defects which is often also used for tracking enhancements and another for source code control.  All this adds more work for the first line manager to exactly figure out the status of the project as he has to track across multiple systems. A lot of us are familiar with putting the enhancement id as part of our checkin into the source control system so that we can generate a report using some script to track the check in to the original requirement. But wouldn’t it be more elegant if all this were neatly integrated and comes out of the box.

 

   Welcome to the world of Team Foundation Server from Microsoft. It not only gives you an integrated system that ties requirements all the way to the code checked in but also provides additional functionality like build system, checkin policies, reporting services, web portal for your project and most importantly a development process methodology that’s central to the product which can be customized to suit your organizational needs.   It also comes with a rich set of API’s that allow you to extend and customize the functionality. You can learn more about TFS from the following links

   I, Kannan Sundararajan, work as part of After Market Solutions team in developer division at Microsoft, mainly focused on reducing customer pain in using our development products by the way of developing after market tools & user education.

 

   I am currently working on releasing a CTP version of Team Foundation Server Permission Manager Tool to simplify the user permission management across the 3 tiers of TFS based on feedback from customers like you. I plan to Blog more about my tool in the coming entries and also seek your input on some of your pain points on using Microsoft Development tools.

 

 
Page view tracker