070-496: Install Team Foundation Server, Configure the Application tier

Here are some notes about installation of TFS and configuration of the application tier.

The Installation and Administration Guides (http://examcr.am/10Ln5E4) have important content for the exam.

Taking a look to the System Requirements here’s some important notes:

  • All of the Operating Systems supported are 64-bits based;
  • Only SQL Server 2008 R2 and 2012 editions are supported;
  • Accounts required for installation – Reporting, Team Foundation Server, Team Foundation Build, Team Foundation Server Proxy, SharePoint Products, SQL Server;
  • The TFS setup will install IIS;
  • SharePoint Foundation 2010 can be installed manually or as part of the TFS installation, it doesn’t need to be in the same server as TFS, but if not installed in the same server it requires Extensions for Windows SharePoint Services on the server that is runnning SharePoint Products;
  • SharePoint Server 2010 Standard and Enterprise versions are supported, but Enterprise edition provides access to 5 extra dashboards.

Installation options considered in the exam: Advanced, Application-Tier only, Upgrading TFS from an earlier release of it, Build services installation, Proxy services installation.

Team Foundation Server Proxy does not provide scalability, but can save bandwidth by caching version control files at the remote location.

Exam Best Bets

  • Download and read the TFS Install and Administration guides http://examcr.am/10Ln5E4
  • Make sure you’re well aware of the system requirements
  • Make sure you’re familiar with multi-server installations
  • Make sure you are confident configuring integration with SharePoint and Reporting Services

Upgrading

Like previous versions, TFS 2012, supports upgrading from Visual Source Safe too, but this version comes with a wizard that simplifies much more the upgrading task.

Lab Management

Setting up environment templates – http://examcr.am/ZEzfgM
Installing and configuring test agents – http://examcr.am/11pcal8
installing and configuring System Center Virtual Machine Manager (basic Virtual Machine Manager installation) – http://examcr.am/ZCTOv3
Creating library shares or resource pools – http://examcr.am/ZCTOv3

Build Agents & Controllers

A Build Service can only be used by one Team Project Collection.
Tagging and binding a controller to a project collection – http://examcr.am/11Ng34t
Adding a build agent - http://examcr.am/15sFEUL

070-496: Administering Microsoft Visual Studio Team Foundation Server 2012

Starting the MCSD: Application Lifecycle Management, I’ll begin by doing the 070-496 exam. Here’s the study material that I’ll be using:

  • http://www.microsoft.com/learning/en-us/exam.aspx?ID=70-496
  • Professional Team Foundation Server 2012 (http://shop.oreilly.com/product/9781118314098.do)
  • http://www.microsoftvirtualacademy.com/training-courses/administering-visual-studio-tfs-2012-exam-496-jump-start

This exam is divided in four parts (about 48 questions):

  • Install and Configure Team Foundation Server – 25%
  • Manage Team Foundation Server – 26%
  • Customize Team Foundation Server – 24%
  • Administer Version Control – 25%

YOW-2012-Martin-Thompson-Mechanical-Sympathy-and-High-Performance-Coding

Martin Thompson is a high-performance and low-latency computing specialist, with experience gained over two decades working with large scale transactional and big-data domains, including automotive, gaming, financial, mobile, and content management. He believes Mechanical Sympathy – applying an understanding of the hardware to the creation of software – is fundamental to delivering elegant, high-performance, solutions.

Here, Martin explains his perspectives on high performance computing (and coding), when to go native versus managed (Can you really write super fast, highly machine-optimized code in Java and .NET? Martin does…). This is a long conversation and well worth your time if performant execution is important to you – yes, the irony of a long chat about highly performant computing doesn’t escape me.

in http://channel9.msdn.com/posts/YOW-2012-Martin-Thompson-Mechanical-Sympathy-and-High-Performance-Coding

Martin Thompson Blog: http://mechanical-sympathy.blogspot.com

Cross Domain Policy Files with Silverlight

There’s a tipical problem when running WCF services in a Silverlight Application: Access to Cross Domain Services.

How to resolve this? Well, it’s simple!

We need to verify that our IIS web directory root (e.g. C:\Inetpub\wwwroot\) has the client access policy file, in order to make it accessible directly at, for example, http://localhost/clientaccesspolicy.xml.

Here’s the content of the file clientaccesspolicy.xml:

<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource include-subpaths="true" path="/"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

This enables access from all urls (domain uri=”*”). You may define a less public access by changing this value.

You may need the crossdomain.xml file also. Here’s the content:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

For more information see:
http://msdn.microsoft.com/en-us/library/cc197955%28v=vs.95%29.aspx

http://www.silverlight.net/learn/data-networking/introduction-to-data-and-networking/how-to-use-cross-domain-policy-files-with-silverlight

Using ModalPopupExtender (Ajax Control Toolkit) inside GridView rows

If you already used Ajax Control Toolkit you know that this has some nice controls to use in ASP.NET applications. One of them is the ModalPopupExtender. This is a great control, that brings great functionality to your web pages and is very simple to use. But if you want to use it with GridView? Well, here’s an example of how to do it.
Basically, we’ll have a GridView where we can display a list of User Groups, and we want to be able to see for each group the users that are associated with it.
The solution to have the ModalPopupExtender working for every row is to set the ModalPopupExtender inside a Repeater and for each row that I have, I will set the TargetControlID to the ImageButton column. This way I can bind the ModalPopupExtender to the GridView Data.

Download ModalPopupExtenderSample Project

So, let’s see how to implement it, but first, here’s some configuration that you should add to the configuration file:

<configuration>
  <system.web>
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
  </system.web>
</configuration>

This is important to be able to set the TargetControlID of the ModalPopupExtender control.
And now, let’s see how to define the ModalPopupExtender inside the Repeater control and the respective Panel and also the main GridView with the Users Group:

<asp:ScriptManager ID="ScriptManagerMain" runat="server" />

<asp:Repeater ID="RepeaterGroupUsers" runat="server"
  OnItemCreated="RepeaterGroupUsersOnItemCreated">
  <ItemTemplate>
    <ajaxToolkit:ModalPopupExtender runat="server" ID="ModalPopupExtenderGroupUsers"
      PopupControlID="PanelGroupUsers" OkControlID="ImageButtonClose"
      CancelControlID="ImageButtonClose"
      PopupDragHandleControlID="PopupHeaderGroupUsers"
      DropShadow="False" Y="100" X="500" BackgroundCssClass="ModalPopupBackground"
      RepositionMode="RepositionOnWindowResizeAndScroll" />
  </ItemTemplate>
</asp:Repeater>

<asp:Panel ID="PanelGroupUsers" runat="server" style="display: none;">
  <table width="100%" class="GroupUsersPopup">
    <tr id="PopupHeaderGroupUsers" class="ModalPopupHeader">
      <td><asp:Label ID="LabelGroupUsers" 
        runat="server">Group Users</asp:Label></td>
    </tr>
    <tr style="vertical-align: top; text-align: left; width: 100%;">
      <td style="font-family: Verdana; font-size: 11px; color: Black;">
        <asp:GridView ID="GridViewGroupUsers" runat="server"
          AutoGenerateColumns="False" Height="100%" Width="100%" DataKeyNames="Id"
          CssClass="GridViewStyle" ViewStateMode="Enabled" ShowHeaderWhenEmpty="True">
          <HeaderStyle CssClass="GridViewHeader" />
          <Columns>
            <asp:BoundField ShowHeader="True" HeaderText="Id" Visible="False" 
              ReadOnly="True" DataField="Id"/>
            <asp:BoundField ShowHeader="True" HeaderText="User Name"
              DataField="Name">
              <ItemStyle Width="98%" CssClass="GridViewStyle" />
              <HeaderStyle CssClass="GridViewLeftHeaderStyle" />
              <ControlStyle Width="98%" />
              <FooterStyle Width="98%" CssClass="GridViewInnerFooterStyle" />
            </asp:BoundField>
          </Columns>
        </asp:GridView>
      </td>
    </tr>
    <tr class="ModalPopupButtons">
      <td>
        <asp:ImageButton ID="ImageButtonClose" runat="server"
          ImageUrl="/Resources/Images/ok_32.png" ToolTip="Close" />
      </td>
    </tr>
  </table>
</asp:Panel>

<table style="font-family: Verdana; font-size: 11px;" width="100%">
  <tr>
    <td colspan="2"
      style="border-width: 0px 0px 1px 0px; border-style: solid; width: 100%;">
      <asp:Label ID="labelTitle" runat="server"
        CssClass="titlePage">User Groups</asp:Label>
    </td>
  </tr>
  <tr>
    <td colspan="2">
      <asp:Label ID="labelErrorMessage" runat="server" Visible="False"
        ForeColor="Red" />
    </td>
  </tr>
  <tr>
    <td colspan="2" style="font-family: Verdana; font-size: 11px; color: Black;">
      <asp:GridView ID="GridViewGroups" runat="server" AutoGenerateColumns="False"
        Height="100%" Width="100%" DataKeyNames="Id" CssClass="GridViewStyle"
        OnRowDataBound="GridViewGroupsOnRowDataBound" ViewStateMode="Enabled"
        ShowHeaderWhenEmpty="True" ShowFooter="True">
        <HeaderStyle CssClass="GridViewHeader" />
        <Columns>
          <asp:BoundField ShowHeader="True" HeaderText="Id" Visible="False" 
            ReadOnly="True" DataField="Id" />
          <asp:BoundField ShowHeader="True" HeaderText="Group Name"
            DataField="GroupName">
            <ItemStyle Width="200" CssClass="GridViewStyle" />
            <HeaderStyle CssClass="GridViewLeftHeaderStyle" />
            <ControlStyle Width="98%" />
            <FooterStyle Width="200" CssClass="GridViewLeftFooterStyle" />
          </asp:BoundField>
          <asp:BoundField ShowHeader="True" HeaderText="Group Description"
            DataField="GroupDescription">
            <ItemStyle Width="300" CssClass="GridViewStyle" />
            <FooterStyle Width="300" CssClass="GridViewInnerFooterStyle" />
            <ControlStyle Width="98%" />
            <HeaderStyle CssClass="GridViewInnerHeaderStyle" />
          </asp:BoundField>
          <asp:TemplateField>
            <ItemTemplate>
              <asp:ImageButton ID="ImageButtonManageUsers" runat="server"
                ImageUrl="/Resources/Images/users_32.png" CommandName="EditUsers"
                OnClick="ImageButtonManageUsersOnClick" />
            </ItemTemplate>
            <ItemStyle Width="32" Height="32" CssClass="GridViewStyle" />
            <FooterStyle Width="32" CssClass="GridViewRightFooterStyle">
            </FooterStyle>
            <HeaderStyle CssClass="GridViewRightHeaderStyle" />
          </asp:TemplateField>
        </Columns>
      </asp:GridView>
    </td>
  </tr>
</table>

<asp:HiddenField ID="HiddenFieldSelectedRowIndex" runat="server" />

The code behind:

#region Page Events
protected void Page_Load(object sender, EventArgs e)
{
  if (!this.IsPostBack)
  {
    this.Groups = Services.GetData();
    BindGroupsToGridView();
  }
}
#endregion

#region Properties
private List Groups
{
  get
  {
    return (List)this.Session["groups"] ?? new List();;
  }
  set
  {
    if (value == null)
    {
      value = new List();
    }

    this.Session.Add("groups", value);
  }
}

private ObservableCollection IdList
{
  get
  {
    return (ObservableCollection)this.Session["idlist"] ?? new ObservableCollection();
  }
  set
  {
    if (value == null)
    {
      value = new ObservableCollection();
    }

    this.Session.Add("idlist", value);
  }
}
#endregion

#region Methods
private void BindGroupsToGridView()
{
  this.labelErrorMessage.Visible = false;
  try
  {
    this.IdList = new ObservableCollection();
    this.GridViewGroups.DataSource = this.Groups;
    this.GridViewGroups.DataBind();

    this.RepeaterGroupUsers.DataSource = this.IdList;
    this.RepeaterGroupUsers.DataBind();
  }
  catch (Exception exception)
  {
    this.labelErrorMessage.Text = "Error: " + exception.Message;
    this.labelErrorMessage.Visible = true;
  }
}

private void BindGroupUsersToGridView(UserGroupContract group)
{
  this.labelErrorMessage.Visible = false;
  try
  {
    this.GridViewGroupUsers.DataSource = group.Users;
    this.GridViewGroupUsers.DataBind();
  }
  catch (Exception exception)
  {
    this.labelErrorMessage.Text = "Error: " + exception.Message;
    this.labelErrorMessage.Visible = true;
  }
}
#endregion

#region Events
protected void RepeaterGroupUsersOnItemCreated(object sender, RepeaterItemEventArgs e)
{
  if (e.Item.ItemIndex < this.IdList.Count)
  {
    foreach (var control in e.Item.Controls)
    {
      if (control is ModalPopupExtender)
      {
        var modalPopupExtender = ((ModalPopupExtender)control);
        var targetControlId = this.IdList[e.Item.ItemIndex];
        modalPopupExtender.TargetControlID = targetControlId;
        modalPopupExtender.ID = "ModalPopupExtender" + e.Item.ItemIndex;
      }
    }
  }
}

protected void GridViewGroupsOnRowDataBound(object sender, GridViewRowEventArgs e)
{
  foreach (Control ctrl in e.Row.Cells[3].Controls)
  {
    var btn = ctrl as IButtonControl;
    if (btn != null && btn.CommandName == "EditUsers")
    {
      var button = ((WebControl)ctrl);
      var clientName = button.ClientID.Replace('_', '$');
      var value = "javascript:return ShowGroupUsers(" + e.Row.RowIndex + ", '" + clientName + "');";
      button.Attributes.Clear();
      button.Attributes.Add("onClick", value);

      var temp = this.IdList;
      temp.Add(clientName);
      this.IdList = temp;
    }
  }
}

protected void ImageButtonManageUsersOnClick(object sender, ImageClickEventArgs e)
{
  this.labelErrorMessage.Visible = false;
  try
  {
    var selectedRowIndex = Convert.ToInt32(this.HiddenFieldSelectedRowIndex.Value);

    var group = this.Groups[selectedRowIndex];
    if (group != null)
    {
      BindGroupUsersToGridView(group);
    }

    #region Let Modal Popup stay visible
    if (selectedRowIndex < this.RepeaterGroupUsers.Items.Count)
    {
      var item = this.RepeaterGroupUsers.Items[selectedRowIndex];
      if (item != null)
      {
        foreach (var control in item.Controls)
        {
          if (control is ModalPopupExtender)
          {
            var modalPopupExtender = ((ModalPopupExtender)control);
            modalPopupExtender.Show();
          }
        }
      }
    }
    #endregion
  }
  catch (Exception exception)
  {
    this.labelErrorMessage.Text = "Error: " + exception.Message;
    this.labelErrorMessage.Visible = true;
  }
}
#endregion

Basically, when each row is binded to the grid you’ll just need to go to the associated ModalPopupExtender (that’s inside the repeater) and set the TargetControlID to the ImageButton of the row. It’s important to keep track of all the ID’s for the images.

Here’s a preview of the output:

And here you can download the project sample: ModalPopupExtenderSample Project. Just unzip it and start playing with it. ;)