TFS SP1 Beta Released

Almost a year after TFS release in last november, TFS SP1 beta is finaly available. It is available through Microsoft Connect center. It is very important that this release include not only bug fixes. Among main improvements:

  • Performance improvements
  • Basic authentication suppotr (for extranet access scenarios)
  • Customer contros support in WI forms
  • Better merge history information
  • Separated OLAP server installation support
  • Office 2007 (Project and Excel only for now) support

Thanks Brian Harry for update.

Cross-Posted from here

Our Team System Blog

Our group, which specilised in Team System consulting and implementation finaly start to blog. From now on I will post my VSTS related entries there. And today, read VSS to Team System Migration Checklist. Cross-Posted from here

InteropForm Toolkit - .NET - VB6 bridge part 2

Ok, as promised, I finished C# project and item templates to be used with Interop Form Toolkit. In addition I extended Interop Wrapper Add-In to support C# code generation. You can download template, Add-In and full source code from here. I be glad to here what do you think.

Cross-Posted from here

InteropForm Toolkit - .NET - VB6 bridge

Do you have existing VB6 system?
Would you like to gradually migrate them into .NET world?
Can you afford "all or nothing" migration?

After a long period of talking and expectation Interop Form Toolkit is finally released. It is VS2005 Add-In together with project template and documentation, which allows to easy creating mixed VB6/VB.NET application. Toolkit automates interop objects generation and provides an easy way of VB6 - .NET communication through events and shared state. Toolkit is surprisingly fare documented and came with two sample project.

After couple of hours playing with new toy, one thing I could not understand is "why it supports VB.NET only?" It happens that I personally prefer C# these days... So with a little help of my File Disassembler buddy I translated project template into C#. Existing Add-In generates wrapper classes in VB.NET, and it should be translated also. Now I have simple, fully functioning, combined C#-VB6 sample. It is about 2:30 in the morning on my clock, so I'll recreate Add-In tomorrow (and will, hopefully, post it along with C# project template).

Cross-Posted from here

Atlas Control Toolkit Refresh Released

First refresh of "Atlas" Control toolkit is out. You wiil found four new controls there, some new helpers and fixes. You can download it from here. Go for it!

Cross-Posted from here

Atlas Controls Toolkit Next Drop on Its Way

Next version of Atlas Controls Toolkit will be out (probably) during next week. It will include Safari support, existing controls improvement and new extenders. Thanks Shawn for update (teaser :)).

Cross-Posted from here

Visual Studio Express Editions will Stay Free

If you missed it here, it is a great news. Originally Express edition were announced as free for on year. After 5 million downloads, Microsoft decide to make those editions permanently free. You can consult this comparison table to decide if Express edition is good enough for you.

Cross-Posted from here

Team System Licensing

I am frequently asked lately by client about Team System pricing and licensing. So just to summarize correct links in one place:
Team system Licensing Overview
Pricing
Team System in Volume Licensing

Cross-Posted from here

Atlas Talk at Tech-Ed Israel

I am going to speak at Tech-Ed Israel about Atlas. It is planned to be the only lecture at Tech-Ed related to ASP.NET. Anybody, who would like to attend (or just planning to download presentation and demos later), the time for suggestions is now.

What would you like to hear? What do you think is wrong with ASP.NET today?  What feature you missing most?

Cross-Posted from here

Microsoft Going Open-Source with Atlas Control Toolkit

Finally first drop of Atlas Control Toolkit is out. If you are interested to play with it, you can get it here. It contains bunch of controls together with set of VSI templates for new controls development. It not even beta, just little preview of direction, but is worth trying. There are many more controls planed.

More interesting is that MS guys are planning to setup open-source environment for toolkit development. Way to go! There is so much to do (starting with decent design time support, for example), and we are REALLY like to help!

Cross-Posted from here

Finally Moving

My Blog located at dotnetjunkies for about a year already. It is a place for my findings about .NET dark places, technology news, web development etc. It is time to move now. From now on you will find me at here.
Please come to visit, bring your thoughts and comments.

PS. I'll cross post for a wile to both places.

Cross-Posted from here

WinForm TextBox.AppendText

Apparently this point is commonly overlooked:

Avoid using TextBox.Text += ... construct to build long content.
Use TextBox.AppendText instead. AppendText internally set selection after last character in Textbox and then replace selection with supplied text using SendMessage API. This method is more effective by order of multitude. Note that after AppendText invocation textbox scrolled down to the last line. This is making difference in textboxes with long content (and scrollbar).

Some GC Mode Issues

.NET Garbage Collector design to support two distinct modes: server and workstation.
In server mode GC creates one GC heap and one relative GC thread for each processor. Each one of these threads performs collection in parallel. Server mode available on multi-processor machines only and shows good throughput and scalability.
Workstation mode is default and only one available on single processor machine. In FW 1.0 and 1.1 server mode can be used only in unmanaged hosting environment. ASP.NET for example loads web applications in server mode. In FW1.1 and 2.0 GC mode could be controlled by configuration file entry.
Following node in configuration mode switches GC into server mode:
<CONFIGURATION>
   <RUNTIME>
      <GCSERVER enabled="true" />
   </RUNTIME>
</CONFIGURATION>
The first challenge is to recognize in what mode our server application GC is actually running. In FW1.x it is easy. Workstation mode GC loaded from mscorwks.dll, server mode GC will use mscorsrv.dll. You can use Task Manager or Process Explorer from www.sysinternals.com to check this. In FW 2.0 it is trickier. Both GC modes combined in mscorwks.dll.
Now we have new property GCSettings.IsServerGC which is return true in case that GC running in server mode.
The last tip is: be careful with your configuration file if you want to activate GC in server mode. If you'll try to use any non ASCII characters GC will be loaded gracefully in workstation mode regardless of gcServer tag. See this issue http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=55947061-2b06-4325-b1ef-bdfa9f0af9ec

Client Side ''onsubmit'' Action

There are two ways to add some client-side processing before ASP.NET 2.0 page submitted.
1. Add onsubmit attribute to Form tag in aspx file
2. Use this.Page.ClientScript.RegisterOnSubmitStatement method
Is there any difference?
The answer is processing order.
When aspx page being processed internal collection (_registeredOnSubmitStatements) created which holds all submit statements in order of RegisterOnSubmitStatement calls. Value of onsubmit attribute from aspx added at the end. Client side script created from this collection as statements of WebForm_OnSubmit function.
Now, when the order is particulary importemnt? It will be if we will use validator controls. Validator controls that allows client side script also register submit statement (through BaseValidator class) at PreRender stage. If client side validation fails, any submit statement that follows will not be executed. This behavior is very useful in some scenarios but unwanted in others.
The suggestion is:
- If you need to execute client script on page submit regardless of validation result (submit attempt), use RegisterOnSubmitStatement method before PreRender (for example in Page_Load).
- If you want to execute script only after successful validation, use onsubmit attribute.

HowTo Skip Server Side Validation

ASP.NET button have nice property CausesValidation which allows to prevent client side validation when button clicked. Common, recomended pattern states that any validation performed on client should be done again at server. Suppose we use CustomValidator control with both client and server validation functions. We can bypass client validation using CausesValidation property, but we will be stoped by server validation. Would it be nice (logical) to bypass all validation on postback event raised by button with CausesValidation property set to false? Let's see how can we make this happen. The direct approach is to override Page.Validate method. in this method we'll check if event raised by button with CausesValidation=false and will call real Validate only if not. I probably could reproduce ASP.NET code used to retrieve from Request event source control, but here I am taking shortcut. We'll use private property of Page _registeredControlThatRequireRaiseEvent which is instantiated by ASP.NET. A bit of reflection at it's done:

public override void Validate()
{
   Button btn = typeof(Page).InvokeMember("_registeredControlThatRequireRaiseEvent",
                                        BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, this, null, null) as Button;
   if (btn != null && !btn.CausesValidation)
      return;
   base.Validate();
}

HowTo Change Master Page Dynamically at Runtime

Changing MasterPage dynamically is a simple task, but there is a catch. MasterPage can be changed in PreInit page or earlier. At this stage control tree is not constructed yet. The question is: "How can we use postback event to change MasterPage?" Usual solution for this problem is to save selected MasterPage file name into session, reload page and in PreInit set MasterPage according to persisted value. This works but requires additional roundtrip. Another solution is to intercept postback events in PreInit and process it, so here it is:


ASPX:
@ Page MasterPageFile="~/MasterPage.master" Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div>
<asp:DropDownList ID="MasterSwitch" runat="server" AutoPostBack="true">
<asp:ListItem Text="Simple Layout" Value="MasterPage.master">asp:ListItem>
<asp:ListItem Text="Complex Style" Value="MasterPageComplex.master">asp:ListItem>
asp:DropDownList>
div>
asp:Content>


Codebeside:

using
System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Default : System.Web.UI.Page
{
   protected void Page_PreInit(object sender, EventArgs e)
   {
      switchMaster();
  
   protected void Page_Load(object sender, EventArgs e)
   {
      if (!IsPostBack)
      {
         Session[
"MasterSwitch"] = this.MasterSwitch.UniqueID;
      }
   }
   private void switchMaster()
   {
      if (IsPostBack)
      {
         // Get control that fire postback event
         string eventTarget = Request.Form["__EVENTTARGET"];
         if (String.IsNullOrEmpty(eventTarget))
            return;
         // At this stage we don't have control tree yet,
         // so we'll use previosly saved control ID
         string switchControlName = (string)Session["MasterSwitch"];
         if (String.IsNullOrEmpty(switchControlName))
            return;
         if (String.Compare(eventTarget, switchControlName, true) != 0)
            return;
         setMaster(Request.Form[eventTarget]);
      }
   }
   private void setMaster(string masterName)
   {
      if (String.IsNullOrEmpty(masterName))
         return;
      // In real implementation some logic to convert
      // selected value into real MasterPage File Name should be here
      if (String.Compare(this.MasterPageFile, masterName, true) != 0)
         this.MasterPageFile = masterName;
   }
}

Visual Studio Tools for Office Learning Guide

Impressive collection of articles related to VSTO development. Check it out:

http://searchvb.techtarget.com/generic/0,295582,sid8_gci1167935,00.html

Prevent Postback Events from Firing on Page Refresh

One annoying behavior of ASP.NET pages is a replay of postback events when user hit refresh (F5) in browser.
This behavior is easily reproducible:
Place ASP button on Web Form
1. Add some code to Button_Click event
2. View page in browser
3. Check that your code being executed when you hit button
4. Refresh page and observe that your code being executed once again

Explanation is also simple. As far as the browser goes, when user hits refresh, exact previous request sent to server. This way server has no clue if it is postback event, first page hit or refresh.

The only workaround I found based on fact that client side onsubmit event is not fired on refresh. This being said, you can place 'stamp' counter into session and hidden field on page, increment it in submit event and compare to session version back at server.

Complete solution skeleton will look as follows:
ASPX:
<form id="Form1" onsubmit="var o=getElementById('__REFRESHSTAMP');var i=Number(o.value);i++;o.value=i;" 
       method="post" runat="server">
 <asp:button id="Button2" Text="Button" runat="server"></asp:button>
 <input id="__REFRESHSTAMP" type="hidden" value="1" runat="server">
 <asp:label id="Label1" runat="server">False</asp:label>
</form>

Codebehind (Designer generated code skipped):
public class WebForm1 : System.Web.UI.Page
{
   protected System.Web.UI.WebControls.Button Button1;
 
   protected System.Web.UI.HtmlControls.HtmlInputHidden __REFRESHSTAMP;
   private bool m_RefreshStamped;
   protected System.Web.UI.WebControls.Label Label1;
   private bool m_IsRefresh;
   private bool IsRefresh
   {
      get
      {
         if (!this.m_RefreshStamped)
            this.m_IsRefresh = checkRefresh();
         return this.m_IsRefresh;
      }
   }
   private int getValue(string val)
   {
      if (val == null || val.Length == 0)
         return 0;
      return Int32.Parse(val, CultureInfo.InvariantCulture);
   }
   private bool checkRefresh()
   {
      this.m_RefreshStamped = true;
      string stampKey = String.Concat(this.ToString(), "__REFRESHSTAMP");
      int prevStamp = getValue(this.Session[stampKey] as string);
      int stamp = getValue(this.__REFRESHSTAMP.Value);
      if (stamp > prevStamp) // Postback
      {
         this.Session[stampKey] = stamp.ToString(CultureInfo.InvariantCulture);
         return false;
      }
      return true;
   }
   private void Button1_Click(object sender, System.EventArgs e)
   {
      this.Label1.Text = this.IsRefresh.ToString();
      if (!this.IsRefresh)
         this.Button1.Text = "Clicked at: " + DateTime.Now.ToLongTimeString() ;
   }
}

Notes:
1. You should implement this for each page you want to process.
2. You should reset session stamp before redirecting from page.
3. I would suggest constructing complete solution as custom control with IsRefresh property and Clear method.

Team Foundation Server RC on its way

At last, Release Candidate should be out and awilable on Tuesday, February 7th. Thanks Jeff.