Export (0) Print
Expand All

Hosting ActiveX Controls in SharePoint Foundation 2010 (Wrox)

SharePoint 2010

Summary: Learn how to integrate ActiveX controls in Microsoft SharePoint Foundation 2010 applications.

Wrox logo

Wrox SharePoint Books

This article discusses how to host ActiveX controls in Microsoft SharePoint 2010 in order to provide additional functionality in web browsers. SharePoint 2010 uses ActiveX controls to collect digital signatures, open Microsoft Office applications, and display the presence icon next to the names of users in your SharePoint sites. This article describes how to add ActiveX controls to web pages and then activate them by clicking a custom button on the SharePoint 2010 ribbon. The code sample uses an ActiveX control to open Windows Media Player and play a media file that is located in a SharePoint document library. If you want to create a new ActiveX control instead of reusing one, see the ActiveX Controls (Overviews and Tutorials) on the MSDN website.

The ActiveX framework enables you to create packaged software that can be reused in desktop and web applications. Usually, the packaged software consists of user interface controls called ActiveX controls that contain reusable functionality. For example, an ActiveX control that enables you to collect signatures can be used by the program that originally installed it and in your own custom developed application as well. You can write ActiveX controls in multiple programming languages, including C++, Visual Basic, C#, and other CLR-based languages, and the controls can be used in applications that are written in different programming languages including those that are not CLR-based.

In many web applications, including SharePoint 2010, ActiveX controls provide additional functionality to browsers such as accessing the user’s file system or interacting with the operating system and installed applications. Internet Explorer supports ActiveX controls by default. However, you can enable ActiveX support in other browsers by using plug-ins, such as the one for Mozilla Firefox.

To use a custom ActiveX control in your webpage, you must add an <object> tag or a <script> block to a page that references your custom control. The custom control can be installed beforehand, as Microsoft Office 2010 does, or it can be installed when the page is accessed by the web browser, as with the digital signature control in InfoPath Forms Services.

Adding an <object> tag to the webpage instantiates the ActiveX control as soon as the page finishes loading. If this is an expensive operation, you might consider adding the <object> tag to the page from a JavaScript function in a <script> block. Then, the ActiveX control is only instantiated when you call the JavaScript function. It is easier to use an <object> tag than a <script> block to instantiate the ActiveX control because writing additional JavaScript code is unnecessary.

To add an ActiveX control to any webpage, use the <object> tag and specify a value for the classid or the progid attribute. Use the classid attribute to specify the ActiveX control to display by using its class identifier (GUID). Use the progid attribute to specify the ActiveX control by its programmatic identifier instead. You cannot use both the classid and progid attributes on the same <object> tag.

When an ActiveX DLL is installed, the class and programmatic identifiers of its ActiveX controls are added to the registry of the user’s computer. The browser can use either the class or the programmatic identifier to load the control to display on the page. The following code example displays the ActiveX control that enables you to drag files onto the Upload Multiple Documents page, as shown in Figure 1.

<OBJECT id=idUploadCtl name=idUploadCtl 
    classid=CLSID:07B06095-5687-4d13-9E32-12B4259C9813 width=638 
    height=261>
<PARAM NAME="BorderStyle" VALUE="None">
<PARAM NAME="CurrentAutoScaleDimensions" VALUE="6, 13">
<PARAM NAME="AllowDrop" VALUE="True">
<PARAM NAME="BackColor" VALUE="Window">
<PARAM NAME="CausesValidation" VALUE="True">
<PARAM NAME="Cursor" VALUE="Arrow">
<PARAM NAME="Enabled" VALUE="True">
<PARAM NAME="Font" VALUE="Tahoma, 11world">
<PARAM NAME="ForeColor" VALUE="76, 76, 76">
<PARAM NAME="Location" VALUE="157, 292">
<PARAM NAME="Margin" VALUE="3, 3, 3, 3">
<PARAM NAME="MaximumSize" VALUE="0, 0">
<PARAM NAME="MinimumSize" VALUE="0, 0">
<PARAM NAME="Name" VALUE="UploadCtl">
<PARAM NAME="Size" VALUE="638, 261">
</OBJECT>

Figure 1. Upload Multiple Documents page

Upload Multiple Documents page

In the preceding code example, the classid attribute specified the class identifier of the upload control. The value for the classid attribute is in the format CLSID:guid, where guid is the class identifier of the ActiveX control. The progid attribute could have been used instead, with the value STSUpld.UploadCtl.

The id and name attributes of the <object> tag reference the control from client-side JavaScript. The width and height attributes specify the size of the control. The <object> tag contains several <param> tags. The <param> tag enables you to pass any values to the control that it might need when the control is displayed on the webpage. The <param> tags are unique to that ActiveX control, and you can use many <param> tags or none at all. Finally, the <param> tags do not have to be in any particular order.

One final attribute of the <object> tag that you might use is the codebase attribute. The codebase attribute indicates the location a .cab installation file containing the ActiveX control that the browser can download if the ActiveX control has not been installed on the local computer. A .cab file is a Microsoft Cabinet compressed archive and contains a manifest file that has instructions to the operating system on how to install the ActiveX controls inside it. The following code snippet shows an <object> tag that uses the codebase attribute.

<object id='eula.DSigCtrl' 
    CLASSID='CLSID:5EEE5BF6-DC9E-43be-9100-BF19643943C5'
    CODEBASE='http://local.demo.com/_layouts/DSigCtrl.cab#Version=-1,-1,-1,-1'>
    <param name='DSigControlID' value='eulaControl' />
</object>

SharePoint uses the ActiveX controls listed in Table 1 that Microsoft Office 2010 installs during setup. These controls enable modification of multiple documents and items at a time, start client-side Office applications to edit documents, and enable other functionality that the browser does not support by default. You can find the DLL files that contain these controls in the %ProgramFiles%\Microsoft Office\Office14\ directory.

Table 1. List of SharePoint ActiveX controls

ProgID

Description

DLL File

STSUpld.CopyCtl

Copies a document in a list to another location.

STSCOPY.DLL

DiagramLaunch.DiagramLauncher

Starts Microsoft Visio 2010 to create a new Visio diagram.

DGRMLNCH.dll

SharePoint.ExportDatabase

Starts Microsoft Access 2010 to create or export the data from a linked table to a SharePoint list.

OWSSUPP.dll

ListNet.ListNet

Displays a SharePoint list in DataSheet View, which enables the user to edit multiple items at the same time.

STSLIST.dll

Name.NameCtrl

Displays presence information for the SharePoint users in the site.

NAME.dll

OISCTRL.OISClientLauncher

Starts Microsoft Office Picture Manager for uploading images to a Picture Library.

OISCTRL.dll

SharePoint.OpenDocuments

Starts the appropriate client application when a document is edited in a document library.

OWSSUPP.dll

SharePoint.OpenXMLDocuments

Starts Microsoft InfoPath 2010 to create or edit XML documents in a document library.

inlaunch.dll

SharePoint.SpreadsheetLauncher

Imports lists from Microsoft Excel spreadsheets into the current SharePoint site.

OWSSUPP.dll

SharePoint.StssyncHandler

Returns the name of the application to synchronize calendars and contacts between Microsoft Outlook and SharePoint.

OWSSUPP.dll

TaskLaunch.TaskLauncher

Exports tasks from SharePoint to Microsoft Project 2010.

NAMEEXT.dll

STSUpld.UploadCtl

Enables the user to upload multiple documents to a document library at the same time.

STSUPLD.dll

Many of the ActiveX controls in SharePoint execute when the user clicks a button in the ribbon while viewing a list or document library. Examples include the Export to Excel, Create Visio Diagram, Open with Access, and Open Schedule buttons in the Connect & Export section on the ribbon's List tab shown in Figure 2. Each button uses a different ActiveX control to provide the functionality for that button.

Figure 2. List tab for a SharePoint generic list

List tab for a SharePoint generic list

If written by a malicious party, ActiveX controls can do serious harm to your computer by altering or erasing files, installing viruses, or stealing your personal information. Therefore, ActiveX controls have digital signatures to identify the control's publisher, using a certificate that is obtained from a Trusted Root Certification Authority such as VeriSign so that you know who created the control. In addition, when users access a webpage with an ActiveX control, a message prompts them to allow the control to run.

Figure 3. ActiveX control permission prompt

ActiveX control permission prompt

If you trust the publisher of the control and the website using it, click the Allow button to let the browser display the ActiveX control. Otherwise, close the prompt. If you do not allow the ActiveX control to display on the page, some functionality of the page might not work.

The browser's security settings represent the final hurdle in running ActiveX controls. Internet Explorer classifies websites into four zones, as follows:

  • Internet Zone—Prompts the user to allow ActiveX controls every time.

  • Local Intranet Zone—Prompts the user to allow ActiveX controls if the ActiveX control has not been previously allowed.

  • Trusted Sites Zone—Same as Local Intranet Zone except that the user is also prompted to install the ActiveX control if not previously installed.

  • Restricted Sites Zone—Does not allow ActiveX controls to run.

When you access your SharePoint site, you should make sure that the site is added to the Local Intranet or Trusted Sites zones to allow the SharePoint ActiveX controls to run with a minimum of interruption to the user.

To add a site to the Local Intranet or Trusted Sites zone, follow these steps.

Click Tools on the browser's menu bar and then click Internet Options on the drop-down menu.

Click the Security tab in the Internet Options dialog box, choose the Local Intranet or Trusted Sites zone, and then click Settings.

Figure 4. Internet Options dialog box

Internet Options dialog box

Note Note

If your site is public, the user might not allow your control to run. When that occurs, you must inform the user that their decision to disallow the ActiveX control will result in a less than optimal browsing experience of your site.

If you chose Local intranet, the dialog box shown in Figure 5 appears.

Figure 5. Local intranet dialog box

Local intranet dialog box

To display the dialog box, click Advanced.

Figure 6. Local intranet dialog box

Local intranet dialog box

If you chose Trusted Sites, the dialog box shown in Figure 7 appears. In the similar dialog boxes shown in Figures 6 and 7, the URL of the current site should already be populated in the text box, so click Add to add the current site to the zone that you chose.

Figure 7. Trusted Sites dialog box

Trusted Sites dialog box

Click OK, closing each dialog box until the Internet Options dialog box shown in Figure 4 is closed.

Note Note

If your SharePoint site uses Windows Authentication and your computer is a member of the SharePoint server's domain, you might want to add the site to the Local Intranet zone to have your Windows credentials automatically sent to the SharePoint server when you browse to your site.

Some ActiveX controls do not have a visual component. In those cases, you must add JavaScript functions to the page to interact with them. When the user clicks a button on the webpage, the button calls the JavaScript function that invoked the ActiveX control. The following code example shows the ExportDiagramJavaScript method, called when the user clicks the Create Visio Diagram button shown in Figure 8.

Figure 8. Create Visio Diagram button

Create Visio Diagram button

function ExportDiagram(weburl,listguid, listid, listname, viewname, 
    viewguid)
{ULSsa6:;
    if(g_objDiagramLaunch==null)
    {
        var digInstalled=GetCookie("digInstalled");
        if(digInstalled !=null && digInstalled !='0')
        {
            try
            {
                g_objDiagramLaunch=new 
                    ActiveXObject("DiagramLaunch.DiagramLauncher");
            }
            catch(e)
            {
                return null;
            }
        }
        else if(digInstalled==null)
            GetDiagramLaunchInstalled();
        else
            return null;
    }
    try
    {
        var bstrTemplate="";
        var bstrURI=weburl;
        var bstrViewGUID=viewguid;
        var bstrListGUID=listguid;
        var iListID=listid;
        g_objDiagramLaunch.CreateDiagram(bstrTemplate, bstrURI, 
            bstrViewGUID, bstrListGUID, listname, viewname, iListID);
    }
    catch(e)
    {
        var L_DiagramLaunchFail_Text="Unable to create diagram.";
        alert (L_DiagramLaunchFail_Text);
    }
}

In the preceding code example, a new instance of the DiagramLauncher control is created by calling the ActiveXObject constructor with the ProgID value DiagramLaunch.DiagramLauncher. The new instance is stored in the g_objDiagramLaunch variable and used later in the function to call the CreateDiagram method, which opens Microsoft Visio 2010 with the URL of the current site, the current list's and view's GUID identifiers, the current list's and view's titles, and the ID number of the list template.

To host a custom ActiveX control in SharePoint, you have several options. You can add an <object> tag to the Content Editor Web Part on a Web Part Page. You can add <object> and <script> tags to Web Part, Application, and Master Pages by using SharePoint Designer 2010 and Visual Studio 2010. You can also add <script> tags by adding controls to the SharePoint ribbon.

To create a project to add controls to the SharePoint ribbon, follow these steps.

Open Visual Studio 2010 from the Start menu.

Click File, click New, and then click Project on the menu.

In the New Project dialog box, select Visual C# > SharePoint > 2010 from the pane on the left and then select Empty SharePoint Project from the pane on the right side.

Figure 9. New Project dialog box

New Project dialog box

In the Name text box, type ActiveXHosting and then click OK. When the SharePoint Customization Wizard dialog box appears, type the URL of your SharePoint site into the text box, select the first radio button, and then click Finish.

Figure 10. SharePoint Customization Wizard dialog box

SharePoint Customization Wizard dialog box

Note Note

Selecting the first radio button configures the project to deploy as a sandboxed solution, which allows it to run under fewer privileges than a farm solution.

After the new project opens in Visual Studio, right-click your project, choose Add, and then click New Item from the context menu.

When the Add New Item dialog box appears, select SharePoint from the pane on the left and select Empty Element from the list on the right side. Type AddWMPButton in the text box, and then click Add to create the element file.

Figure 11. Add New Item dialog box

Add New Item dialog box

Visual Studio now opens the newly added empty Element file. Element files are XML documents that contain the provisioning instructions SharePoint uses to create lists and libraries, modify the site's ribbon, and create other objects in the site. In this article, you use this element file to add a CustomAction element to add a button to the ribbon. When clicked, the button executes JavaScript code to interact with your ActiveX control. Add the following code in the element file.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="AddWMPButton"
                Location="CommandUI.Ribbon"
                RegistrationType="List" RegistrationId="851">
    <CommandUIExtension>
      <CommandUIDefinitions>
      </CommandUIDefinitions>
      <CommandUIHandlers>
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

The <Elements> element is always the root element in an elements file. All provisioning instructions appear inside the <Elements> element. The <CustomAction> element is used to create a CustomAction control. CustomAction controls are used to add items to menus and controls to the ribbon. The Id attribute of the <CustomAction> element is the CustomAction control's identifier and should be unique. The Location attribute indicates where the CustomAction control should be displayed. Set the Location attribute to CommandUI.Ribbon when you want to customize the ribbon. The RegistrationType attribute indicates when the CustomAction control should be displayed. Because this example applies to a document library, you specify List as the value. The RegistrationId attribute has different meanings, depending on the value for the RegistrationType attribute. When the RegistrationType attribute is set to List, the RegistrationId attribute represents the template ID of the list that you want to apply the CustomAction control to. The value 851 is the ID of the Asset Library template. That means this CustomAction control appears when you navigate to an Asset Library. To find additional values for the RegistrationId attribute, see the Additional Resources section at the end of this article.

The CustomAction element contains the CommandUIDefinitions and CommandUIHandlers elements. The CommandUIDefinitions element contains the controls that you want to add to the ribbon. The CommandUIHandlers element contains the JavaScript to handle the events raised by the CommandUIDefinitions elements.

To add a button to the ribbon, you must add a CommandUIDefinition element and a Button element inside the CommandUIDefinitions element.

<CommandUIDefinitions>
    <CommandUIDefinition 
        Location="Ribbon.Library.Actions.Controls._children">
        <Button
            Id="Ribbon.Library.Actions.PlayInWMP"
            Command="Ribbon.Library.Actions.PlayInWMP"
            Sequence="30"
            Image16by16="/_layouts/images/WAV16.GIF"
            Image32by32="/_layouts/images/WAV32.GIF"
            LabelText="Play in Windows Media Player"
            TemplateAlias="o2" />
    </CommandUIDefinition>
</CommandUIDefinitions>

The Location attribute of the CommandUIDefinition element indicates where on the ribbon the button should be displayed. The value of the Location attribute indicates that the button should be displayed inside the Connect & Export section of the ribbon's Library tab. For additional values, see the Additional Resources section at the end of the article. Table 2 explains how to use the Button element’s attributes.

Table 2. Button element attributes

Name

Description

Id

The unique identifier of the button. You can get a reference to a rendered control in client-side JavaScript by passing this value to document.getElementById.

Command

The command raised when a user clicks the button. This value must match a CommandUIHandler element in the CommandUIHandlers element.

Sequence

Determine where the button appears in relation to the rest of the controls in the Connect & Export section.

Image16by16

The image to show when the button is shown in small and medium modes.

Image32by32

The image to show when the button is shown in large mode.

LabelText

The text to display when the button is shown in medium and large mode.

TemplateAlias

Determines the default sizing mode of the button and how it appears in the section. For example, the value o2 means the button will appear in medium mode and stacked with other controls.

To handle the button's command when the button is clicked, you must add a CommandUIHandler element to the file.

<CommandUIHandlers>
    <CommandUIHandler Command="Ribbon.Library.Actions.PlayInWMP"
        CommandAction="javascript:"
        EnabledScript="javascript:"/>
</CommandUIHandlers>

The CommandUIHandler element provides JavaScript code to determine when the button should be enabled and what happens when the command is raised. The value of the Command attribute must match the Command attribute of the control that you are handling. The values for the CommandAction and EnabledScript always begin with javascript:. The EnabledScript attribute must be set to a Boolean expression that returns true if the control is enabled and false if the control is disabled. This expression is evaluated when the page first renders and when the user manipulates the page in any way. If you omit the EnabledScript attribute, the control is always enabled. The CommandAction attribute must be set to JavaScript code to run when the control raises its command. You can use any code that you could put inside a <script> tag in a webpage.

Because the button starts Windows Media Player so that it can play a music file from the Asset Library, you must add an expression for the EnabledScript attribute that returns true when an item in the Asset Library is selected. SharePoint provides the Client Object Model, which enables you to determine when items are selected. Type the following code as the value for the EnabledScript attribute.

EnabledScript="javascript:
    SP.ListOperation.Selection.getSelectedItems().length > 0"

The SP.ListOperation.Selection class has the getSelectedItems method, which returns an array of the selected items on the page. JavaScript arrays have the length property, which you use to determine whether items have been selected. If any items have been selected, the button is enabled. Otherwise, the button is disabled.

Now you must add script to the CommandAction attribute. Type the following code for the CommandAction attribute to open Windows Media Player when a user clicks the button.

CommandAction="javascript:
    try {
      if (SP.ListOperation.Selection.getSelectedItems().length > 0) {
        var id = SP.ListOperation.Selection.getSelectedItems()[0].id;
        var fileUrl = document.getElementById(id).nextSibling.getAttribute('href');
        fileUrl = document.location.href.substring(0, document.location.href.indexOf('/', 8)) + fileUrl;

        var player = new ActiveXObject('WMPlayer.OCX');
        player.openPlayer(fileUrl);
      }
    } catch (e) {
      alert('Could not launch Windows Media Player.');
    }"

In the preceding code, the first item in the array returned by the getSelectedItems method is obtained to get the ID of the selected item. The selected item's ID is passed to the getElementById method of the document class to get a reference to the selected item. The nextSibling property returns the next HTML sibling of the selected item, which is an anchor tag pointing to the location of the music file the user selected. Anchor tags have an href attribute that indicates the URL of the file. When the URL is obtained, the current page's URL is parsed to get the server address that is prepended to the file's URL. Finally, the ActiveXObject method is called with the ProgID value of the Windows Media Player control to create a new instance of the control, and its openPlayer method is called with the file URL. Windows Media Player opens and starts playing the file as it is streamed from the server. If the user does not have Windows Media Player installed or declines to allow your script to instantiate the ActiveX control, the alert method in the catch block is called instead.

Finally, you add a SharePoint feature to the project. Features let you turn on or turn off functionality in SharePoint. To add a new feature, right-click the Features folder and then click Add Feature. When the feature has opened, type the following values:

  • Title—Windows Media Player Integration

  • Description—Enables user to open Windows Media Player to play media that is stored in SharePoint

  • Scope—Web

Now you are ready to test the solution. Select Debug and then select Start Debugging from the menu bar. Visual Studio builds the project, deploys the generated solution package, activates the feature, and opens the browser to navigate to your SharePoint site.

To test your CustomAction control, you must add an Asset Library to your site. To create an Asset Library, select More Options from the Site Actions menu. In the Create dialog box, select Asset Library and type Music in the text box on the left. Click Create to finish creating the Asset Library.

Figure 12. Create dialog box

Create dialog box

The browser should automatically navigate to the Asset Library after it is created. Click the Library tab shown in Figure 13. Notice that the Play with Windows Media Player button in the Connect & Export section of the Library tab is disabled.

Upload an audio file to the Asset Library, and select it in the list. Notice that the button is now enabled. Click the button to start Windows Media Player and to play the file.

Figure 13. Library tab

Library tab

ActiveX controls enable you to add rich, powerful functionality to your SharePoint sites. You can use them to add a level of interactivity that the browser does not provide and to integrate with desktop applications, providing a seamless experience between SharePoint and client-side applications. ActiveX controls can be installed when the user accesses your web page in SharePoint and you can host ActiveX controls written by Microsoft and other companies or create your own.

Bryan Phillips is a senior partner at Composable Systems, LLC, and a Microsoft Most Valuable Professional in SharePoint Server. He is a co-author of Professional Microsoft Office SharePoint Designer 2007 and Beginning SharePoint Designer 2010 and maintains a SharePoint-related blog. Bryan has worked with Microsoft technologies since 1997 and holds the Microsoft Certified Trainer (MCT), Microsoft Certified Solution Developer (MCSD), Microsoft Certified Database Administrator (MCDBA), and Microsoft Certified Systems Engineer (MCSE) certifications.

The following were tech editors on Microsoft SharePoint 2010 articles from Wrox:

  • Matt Ranlett is a SQL Server MVP who has been a fixture of the Atlanta .NET developer community for many years. A founding member of the Atlanta Dot Net Regular Guys, Matt has formed and leads several area user groups. Despite spending dozens of hours after work on local and national community activities, such as the SharePoint 1, 2, 3! series, organizing three Atlanta Code Camps, working on the INETA board of directors as the vice president of technology, and appearing in several podcasts such as .Net Rocks and the ASP.NET Podcast, Matt recently found the time to get married to a wonderful woman named Kim, whom he helps to raise three monstrous dogs. Matt currently works as a senior consultant with Intellinet and is part of the team committed to helping people succeed by delivering innovative solutions that create business value.

  • Jake Dan Attis. When it comes to patterns, practices, and governance with respect to SharePoint development, look no further than Jake Dan Attis. A transplant to the Atlanta area from Moncton, Canada, Dan has a degree in Applied Mathematics, but is 100% hardcore SharePoint developer. You can usually find Dan attending, speaking at, and organizing community events in the Atlanta area, including code camps, SharePoint Saturday, and the Atlanta SharePoint User Group. When he's not working in Visual Studio, Dan enjoys spending time with his daughter Lily, watching hockey and football, and sampling beers of the world.

  • Kevin Dostalek has over 15 years of experience in the IT industry and over 10 years managing large IT projects and IT personnel. He has led projects for companies of all sizes and has participated in various roles including Developer, Architect, Business Analyst, Technical Lead, Development Manager, Project Manager, Program Manager, and Mentor/Coach. In addition to these roles, Kevin also managed a Solution Delivery department as a Vice President for a mid-sized MS Gold Partner from 2005 through 2008 and later also served as a Vice President of Innovation and Education. In early 2010 Kevin formed Kick Studios as a company providing consulting, development, and training services in the specialized areas of SharePoint and Social Computing. Since then he has also appeared as a speaker at numerous user group, summit, and conference type events across the country. You can find out more about Kevin on his blog, The Kickboard.

  • Larry Riemann has over 17 years of experience architecting and creating business applications for some of the world’s largest companies. Larry is an independent consultant who owns Indigo Integrations and does SharePoint consulting exclusively through SharePoint911. He is an author, writes articles for publication and occasionally speaks at conferences. For the last several years he has been focused on SharePoint, creating and extending functionality where SharePoint leaves off. In addition to working with SharePoint, Larry is an accomplished .Net Architect and has extensive expertise in systems integration, enterprise architecture and high availability solutions. You can find him on his blog.

  • Sundararajan Narasiman is a Technical Architect with Content Management & Portals Group of Cognizant Technology Solutions, Chennai, with more than 10 years of Industry Experience. Sundararajan is primarily into the Architecture & Technology Consulting on SharePoint 2010 Server stack and Mainstream .NET 3.5 developments. He has passion for programming and also has interest for Extreme Programming & TDD.

Show:
© 2014 Microsoft