Blogger Widgets
  • Sharing Photos using SignalR
  • TFS Extenstion - allows copy work items between projects
  • Displaying jquery progressbar with ajax call on a modal dialog
  • Managing windows services of a server via a website
  • Exploring technologies available to date. TechCipher is one place that any professional would like to visit, either to get an overview or to have better understanding.

Search This Blog

Wednesday 30 May 2012

DialogWidth and DialogHeight not working on chrome for showModalDialog

window.showModalDialog is ignoring dialogWidth and dialogHeight on Chrome but works fine on other browsers such as IE, firefox etc. After some tweaking I have found that dialogWidth and dialogHeight should not have "px" in the value ie.. "dialogWidth:100;dialogHeight:200" but other browsers need to have "px" such as "dialogWidth:100px;dialogHeight:200px"

Here is a simple function that can help

 function ModalDialog(sURL, vArguments, ModalDialogHeight, ModalDialogWidth) {
        var sFeatures;

        if (window.showModalDialog) {
            if (!navigator.userAgent.toLowerCase().match('chrome')) {
                ModalDialogWidth += "px";
                ModalDialogHeight += "px";
            }
            sFeatures = "status:no;center:yes;dialogWidth:" + ModalDialogWidth + ";dialogHeight:" + ModalDialogHeight + ";resizable:yes;";
            var returnResult = window.showModalDialog(sURL, vArguments, sFeatures);
            if (returnResult) {
                return returnResult;
            }
        }
        else {
            sFeatures = "status=no,width=" + ModalDialogWidth + ",height=" + ModalDialogHeight + ",menubar=no,scrollbars=no";
            window.margs = vArguments;
            window.open(sURL, "_blank", sFeatures);
        }
    }


After growing wildly for years, the field of computing appears to be reaching its infancy. ~John Pierce

Thursday 24 May 2012

TFS Helper package extension for Visual Studio 2010

VS2010 is well integrated to TFS and has all the features required on day to day basis. Most common feature any developer use is managing workitems. Creating work items is very easy as is copying work items, but what I need is to copy workitem between projects retaining links and attachments. I am sure this is not Ideal and against sprint projects.

I have created a Visual Studio Package that can achieve this. Here is the step-by-step guide

1. Using VS2010 create a project of type "Visual Studio Package"

2. Select language as "C#" and select "Next"

3. Specify package information and select "Next"
4. Now select "Menu Command" and "Tool Window" and select "Next"
5. Specify command options, tool window options and select "Next"
6. De-select test project options and select "Finish". Now we have completed creating a new package project.
7. Add TFS references to the project
8. Make following code changes
VS2010.TFSHelperPackage.GuidList Class
..
public const string guidVSPackage1CmdSetString2 = "6E282364-7C4B-4E12-868D-AC8572708416";
..
public static readonly Guid guidVSPackage1CmdSet2 = new Guid(guidVSPackage1CmdSetString2);
..

VS2010.TFSHelperPackage.PkgCmdIDList Class
..
public const uint cmdidCopyWorkItemAdvanced = 0x100;
..
TFSHelperPackage Class -> Initialize()
protected override void Initialize()
        {
....
 // Create the command for the menu item.
CommandID menuCommandID2 = new CommandID(GuidList.guidVSPackage1CmdSet2, (int)PkgCmdIDList.cmdidCopyWorkItemAdvanced);
MenuCommand menuItem2 = new MenuCommand(CopyWorkItemAdvancedCallback, menuCommandID2);
mcs.AddCommand(menuItem2);
..
}
private void CopyWorkItemAdvancedCallback(object sender, EventArgs e)
{}


Update "TFSHelperPackage.vsct"

 
  
     ....
      
        
      

    
 
....



..



...

    

      
      
    
...

      
    
...


Now GuidSymbol name="guidTFSContextMenu" is very important as value "517" is the id for "Results List" menu item. Refer to Using EnableVSIPLogging to identify menus and commands with VS 2005 + SP1 to find out Menu command Id/GUIDs.
9. Add a new windows form as follows

10. Now update CopyWorkItemAdvancedCallback with following code
private void CopyWorkItemAdvancedCallback(object sender, EventArgs e)
        { using(CopyWorkItemAdvancedForm cw = new CopyWorkItemAdvancedForm(this))
           {
               if(cw.ShowDialog() == System.Windows.Forms.DialogResult.OK)
               {
                   cw.Close();
               }
           }
        }

11. Update CopyWorkItemAdvancedForm code behind as follows
public partial class CopyWorkItemAdvancedForm : Form
    {
        private IServiceProvider _serviceProvider;
        private IWorkItemTrackingDocument _currentDocument;
        private WorkItem _currentWorkItem;
        private WorkItem _newWorkItem;
        private WorkItemStore _workItemStore;

        public CopyWorkItemAdvancedForm(IServiceProvider serviceProvider)
        {
            InitializeComponent();
            _serviceProvider = serviceProvider;
            LoadControls();
        }

        private void LoadControls()
        {
            this.cmbProjects.Items.Clear();
            this.cmbWorkItemTypes.Items.Clear();

            //Load source workitem 
            _currentDocument = WitDocumentHelper.GetCurrentWitDocument(_serviceProvider);
            string selectedItemId = string.Empty;
            if (_currentDocument is IResultsDocument)
            {
                int cnt = ((IResultsDocument)_currentDocument).SelectedItemIds.Length;
                if (cnt > 0)
                {
                    IResultsDocument resultDocument = (IResultsDocument)_currentDocument;
                    selectedItemId = resultDocument.SelectedItemIds[0].ToString();
                    _currentWorkItem = resultDocument.ResultListDataProvider.GetItem(0);
                }
            }
            else if (_currentDocument is IWorkItemDocument)
            {
                // To be completed
            }
            else if (_currentDocument is IQueryDocument)
            {
                // To be completed
            }
            else
            {
                // To be completed
            }

            this.Text = "Create Copy of Work Item with options ... [ " + selectedItemId + "]";

            //Load dropdowns
            var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
            TeamFoundationServerExt ext = dte.GetObject("Microsoft.VisualStudio.TeamFoundation.TeamFoundationServerExt") as TeamFoundationServerExt;
            TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(ext.ActiveProjectContext.DomainUri));

            // Refer to http://msdn.microsoft.com/en-us/library/bb286958.aspx for list of types available with GetService
            _workItemStore = teamProjectCollection.GetService();

            if (_workItemStore != null)
            {
                if (_workItemStore.Projects.Count > 0)
                {
                    foreach (Project prj in _workItemStore.Projects)
                    {
                        this.cmbProjects.Items.Add(prj.Name);

                        if (this.cmbWorkItemTypes.Items.Count == 0)
                        {
                            foreach (WorkItemType wtype in prj.WorkItemTypes)
                            {
                                string wtypeName = wtype.Name;
                                if (!this.cmbWorkItemTypes.Items.Contains(wtypeName))
                                    this.cmbWorkItemTypes.Items.Add(wtypeName);
                            }
                        }

                    }
                }
            }


            this.cmbWorkItemTypes.SelectedIndex = this.cmbWorkItemTypes.Items.IndexOf(_currentWorkItem.Type.Name);
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            if (_currentWorkItem != null)
            {
                CreateNewWorkItem();
                string message = string.Format("Copied Item Successfully !!! \r\n Source Item ID {0} has {1}  Attachments and {2} Links \r\n\r\n Target Item ID {3} has {4} Attachments and {5} Links",
                    _currentWorkItem.Id,
                    _currentWorkItem.Attachments.Count,
                    _currentWorkItem.Links.Count,
                    _newWorkItem.Id,
                    _newWorkItem.Attachments.Count,
                    _newWorkItem.Links.Count);
                MessageBox.Show(message, this.Text, MessageBoxButtons.OK);
            }

            this.DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void CreateNewWorkItem()
        {

            Project targetProject = _workItemStore.Projects[this.cmbProjects.SelectedItem.ToString()];

            WorkItemType wit = targetProject.WorkItemTypes[this.cmbWorkItemTypes.SelectedItem.ToString()];

            _newWorkItem = _currentWorkItem.Copy(wit);

            RelatedLink source2Target = new RelatedLink(targetProject.Id);
            _newWorkItem.Links.Add(source2Target);

            System.Net.WebClient request = new System.Net.WebClient();
            request.Credentials = System.Net.CredentialCache.DefaultCredentials;
            string tempPath = System.IO.Path.GetTempPath();
            if (_currentWorkItem.Attachments.Count > 0)
            {
                foreach (Attachment attach in _currentWorkItem.Attachments)
                {
                    string attachmentPath = Path.Combine(tempPath, attach.Name);
                    request.DownloadFile(attach.Uri, attachmentPath);
                    _newWorkItem.Attachments.Add(new Attachment(attachmentPath));

                }
            }
            _newWorkItem.Save(SaveFlags.MergeLinks);

        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        }
    }

12. Also add a new helper class WitDocumentHelper
 class WitDocumentHelper
    {

        public static IWorkItemTrackingDocument GetCurrentWitDocument(IServiceProvider serviceProvider)
        {
            Debug.Assert(serviceProvider != null);

            EnvDTE.DTE dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
            if (dte.ActiveDocument == null)
                return null; // No active document

            DocumentService docService = (DocumentService)serviceProvider.GetService(typeof(DocumentService));
            if (docService == null)
                return null; // Possibly VSTS WIT is not installed or instantiated yet.

            IWorkItemTrackingDocument doc = docService.FindDocument(dte.ActiveDocument.FullName, serviceProvider);
            return doc; // Caller must release the document after use
        }

    }

This completes the task of creating a package to copy workitem between projects. Complete source code is available on Git via codeplex at tfshelperforvs2010.codeplex.com.

All of the biggest technological inventions created by man - the airplane, the automobile, the computer - says little about his intelligence, but speaks volumes about his laziness. ~Mark Kennedy

Thursday 3 May 2012

ASP.NET MVC login page throwing error "The resource cannot be found"


As per ASP.NET MVC getting the error message "The resource cannot be found" is as simple as verifying if the view/user control does actually exist or name of the view/user control is misspelled.

But in this case that is not the issue because the controller "AccountController" does exist and the view "Login.aspx" also does exist. So have started using google search and tried various suggestions but nothing did work.

Also I have created another sample ASP.NET MVC standard project and have modified web.config to use forms authentication and that works, so the issue is not the environment.

Actually I have missed out a point about some configuration changes I have made to project. The requirement was actually to support "IIS 7" & "IIS 6" as well. The changes I have actually made are

1. Added extra routing in global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default.aspx", // Route name
                "{controller}.aspx/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Default", id = UrlParameter.Optional } // Parameter defaults
            );

            routes.MapRoute(
                "Root",
                "",
                new { controller = "Home", action = "Default", id = UrlParameter.Optional });
        }
2. Added "default.aspx" to project at the root
3. Now add "Page_Load" event to code behind
public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            HttpContext.Current.RewritePath(Request.ApplicationPath);
            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(HttpContext.Current); 
        }
    }

All these changes allows running ASP.NET MVC application on IIS6. All this said I am still unable to find out the fix for this issue. Started looking at the error message again to see if I have missed out any thing, Aha.... I found it. Look at the url on the address bar
http://localhost:49668/Account/Logon?ReturnUrl=%2fdefault.aspx

Lets look at first route map
 routes.MapRoute(
                "Default.aspx", // Route name
                "{controller}.aspx/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Default", id = UrlParameter.Optional } // Parameter defaults
            );

ie.. request for "default.aspx" will use "Home" controller with action as "Default"

Second route map
 routes.MapRoute(
                "Root",
                "",
                new { controller = "Home", action = "Default", id = UrlParameter.Optional });

ie.. request to root of the website to be redirected to "default.aspx", use "Home" controller with action as "Default"

Both are fine but I have missed out default ASP.NET MVC routing which is (ie.. "{controller}.aspx" modified to "{controller}"
 routes.MapRoute(
                "Default", // Route name
               "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Default", id = UrlParameter.Optional } // Parameter defaults
            );

After adding this application started working and I have got the login page.

Treat your password like your toothbrush. Don't let anybody else use it, and get a new one every six months.
~Clifford Stoll

Tuesday 1 May 2012

Unable to debug Visual Studio 2010 addin or suddenly stopped working

I have created a new addin for Visual Studio 2010 using standard addin template. The sample works fine, then I start making some changes and adding more dependencies. Yes got some compilation errors and have fixed them. Now after starting debugging a runtime error is thrown, so fixed that.

Now If I start debugging, the addin no longer gets loaded and also won't show in Addin Manager (VS2010 -> Tools -> Add-in Manager). Now this is really getting me upset.

Used our friend google to find a solution but no luck. So started looking at places where addins were loaded from, aha.. I found the issue.



1. Looking at "C:\Users\Saif\Documents\Visual Studio 2010\Addins" I have found the addin file was renamed from "MyAddin2 - For Testing.AddIn" to "MyAddin2 - For Testing.AddIn_" ie.. an "_" in the end. I think this might have done by visual studio, ie.. since visual studio is unable to load the addin it has renamed by adding "_"

So renaming back from "MyAddin2 - For Testing.AddIn_" to "MyAddin2 - For Testing.AddIn" started loading the addin.

2. Also verify Project Properties -> Debug



1. "Start external program" : "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"
2. "Command line arguments" : "/resetaddin MyAddin2.Connect"
3. "Working directory" : "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\"

The inside of a computer is as dumb as hell but it goes like mad! ~Richard Feynman
Copyright © 2013 Template Doctor . Designed by Malith Madushanka - Cool Blogger Tutorials | Code by CBT | Images by by HQ Wallpapers