Skip to main content
Select a theme:
   
RSS Feed

DefaultFocus property

Ever wanted to make a particular control on a page start out with the focus?  In the past, the only way to do this was to add some javascript to the OnLoad event on the Body tag.   Now, thanks to the DefaultFocus property, it is easy to set the focus.  Simply, specify which control is the default using the DefaultFocus property on the form tag.
 
<form id="Form1"
    defaultfocus="TextBox1"
    runat="server">
    <asp:textbox id="TextBox1"
      runat="server">
    </asp:textbox>
<form>

Varchar(max) Data Type

Here is something new about SQL Server 2005.  The varchar, nvarchar, and varbinary supports a max length.  Instead of being limited to 8000 characters in the past, this new data type supports up to 2GB of data.  No longer do you have to use text, ntext, and image data types.  In fact these data types have been marked for deprecation in the future.

DefaultButton property

Ok, this is probably got to be one of the coolest things that they have added that in not really talked about.  The form tag now supports a property called DefaultButton.  This property allows you to specify which button is clicked when the enter button is pressed.  Even cooler is that you can also specify this property on a panel.  Why this is cool is that on the home page we can have the LocationTime control submit to GetRates when the enter button is pressed.  At the same time, we could also have another textbox that submits to location search whenever the enter button is pressed.
 
Here is an example:
 
<Form id="Form1" runat="server" DefaultButton="GetRatesButton">
</Form>

ImageMap Control

This is another one of those new controls that inherits from WebControl instead of HtmlControl.  What's nice is that you can define hotspots just as you could with the original control, but you can specify whether the control navigates to a particular URL or it does a post back.   To determine what the control does set the HotSpotMode property to either Navigate or PostBack.   To have it go to a particular URL, set the NavigateUrl property.  When you are doing a postback, set the PostBackValue property (which works similarly to the CommandeName property of a button control).
 
Here is an example:
 
<asp:ImageMap id="MyImageMap" ImageUrl="Blah.jpg" hotspotmode="PostBack" OnClick="MyImageMap_Click" runat="server">
     <asp:RectagnleHotSpot top="0" left="0" bottom="50" right="50" postbackvalue="HotSpot1" />
     <asp:RectagnleHotSpot top="50" left="50" bottom="100" right="100" postbackvalue="HotSpot2" />
     <asp:CircleHotSpot" x="200" y="200" radius="25" hotspotmode="Navigate" NavigateUrl="/blah.aspx" />
</asp:ImageMap>
 
In this example, the fire RectangleHotSpot actually does a post back with a value of HotSpot1, and the CircleHotSpot navigates to a new url.  You can also create PolygonHotSpots
 
The event handling method handling the click event would look like this:
 
protected void MyImageMap_Clicked(Object sender, ImageMapEventArgs e)
{
    if (e.Value == "HotSpot1")
    {
         // do something
     }
     else if (e.Value == "HotSpot2")
     {
         // do something else
      }
}
 
As you can see this control is a lot more functional than in the past.

AppendDataBoundItems property for List Controls

Has there ever been a situation where you wanted to bind a drop down list to a data source but also have a static item in there (i.e.: Pick One, Show All Cars, etc.)?  The AppendDataBoundItems property makes this a lot more simple.  Simply add your items at design time, make sure this property is true, and then also set your DataSourceId.  The static items you inserted will then not be overwritten when you bind the data to the control.

AssociatedControlId property of the Label Control

A new property has been added to the label control called AssociatedControlId.  This allows you to link a label to another control on the page.  This is useful for linking to textboxes, dropdownlists, etc.  When this property is set, focus is automatically set to the associated control whenever the label is clicked.

AutoComplete with the TextBox control

One new feature added to the textbox control is the ability to specify custom auto complete sources for textboxes (for browsers that support autocomplete of course).  By creating an AutoCompleteStringCollection, which is just a simple collection, and by binding it to the AutoCompleteCustomSource property of the textbox you can specify where the browser pulls its autocomplete list from.  In order to do this you must also set the AutoCompleteSource property to CustomSource.  You can also specify any of the builtin sources such as AllUrl, FileSystem, HistoryList, etc.  This could prove to be a useful feature for internal applications.

BONUS TIP! FileUpload Control

Since i missed a day this week, I thought I would throw in a bonus tip.  There is now a FileUpload control.  You don't have to use the HtmlInputFile control any more.   This new control actually inherits from the WebControl class as opposed to the HtmlControl class.   Check it out the next time you need to do some file uploading.

New Properties on the Button control

I'll be talking more and more about some of the less hyped features in ASP.NET 2.0.  The Button control has three new properties.  OnClientClick can be used to specify a javascript method to invoke when the button is clicked.  Yeah, it could do this before, but now intellisense won't freak out when previously you tried to use OnClick.   PostBackUrl can be used to post your data to a different page.  UseSubmitBehavior causes the button to emit JavaScript to perform a post (similar to LinkButton controls).

ValidationGroup Property

UPDATE:  I touched on this earlier, but if you want to see a real working sample, go to:
 
 
The Search By Id textbox is in a different validation group than the rest of the search criteria.  Therefore, you can submit a search without filling out the ErrorIdTextBox.  The items are in SourceSafe in the 2.0 branch if you are interested.
 
I think most people have heard of ValidationGroups by now, but I wanted to touch on it, just to make sure.   Many times in the past, there were situations where you had multiple forms on the page that needed to be validated seperately from one another.  A good example is our index page with the Location / Time control and a Location Search textbox.  Today, without special handling, typing something in the location search textbox will cause all of the Location / Time control validators to fire.  This is obviously not the intended behavior.
 
Now a new property has been added to button controls as well as validators called ValidationGroup.  Simply set this property to the same name for all controls that you want to be validated together.  Set a different name for the other controls on your page that you want to be evaluated seperately.  So in the above example, all of the Location / Time control's controls and validators would set ValidationGroup equal to LocationTime.  The Location Search controls could be set to LocationSearch.
 
Here is a quick example of how two different sets of textboxes and butons can be validated seperately:
 
    <asp:TextBox
        id="TextBox1"
        Runat="Server" />
    <asp:Button
        ValidationGroup="Group1"
        Text="Submit"
        OnClick="Group1Click"
        Runat="Server" />
    <asp:RequiredFieldValidator
        ValidationGroup="Group1"
        ControlToValidate="TextBox1"
        Text="(required)"
        Runat="Server" />
   <asp:TextBox
        id="TextBox2"
        Runat="Server" />
    <asp:Button
        ValidationGroup="Group2"
        Text="Submit"
        OnClick="Group2Click"
        Runat="Server" />
    <asp:RequiredFieldValidator
        ValidationGroup="Group2"
        ControlToValidate="TextBox2"
        Text="(required)"
        Runat="Server" />

Like I said, many of you have probably already heard of this feature, but I thought it was worth covering again.

Precompiling

ASP.NET 2.0 offers a variety of compilation options.  As of Beta 2, Web sites can be compiled just like they are in 1.1 (i.e.: binaries with aspx pages left untouched).   As you know, in ASP.NET 1.1, the first time you go to a web page in an application, there is a delay while the Framework compiles the IL code.  In 2.0, this delay can be removed for a customer by going to precompile.axd off of your web application's root.  Going to this URL will simply return a message that says your application has been precompiled successfully (provided there is nothing wrong with your application of course).  Now, the first customer to go to your site will not have to experience any delay visiting the site.
 
ASP.NET applications can aslo be precompiled using the Publish Web Site menu option in Visual Studio 2005.  Using that option, will compile the entire web site (inclucing aspx and ascx files) into a single group of binaries.  This allows the entire site to tbe deployed by moving the bin folder.  This option obviously has its limitations since it could never work with Rhythmyx.  Note: precompile.axd can not be used when you compile with this method, because the application is already precompiled.

DataBinding with Repeaters, etc.

How many times have you typed something like <%# DataBinder.Eval(Container.DataItem, "VehicleType") %>?  Some of you may have already read this, but now you can replace the above with <%# Eval("VehicleType") %>.  This may not be terribly exciting, but it should make your lives easier when trying to remember syntax. 
 
As a side note, the Visual Studio 2005 IDE now has improved Intellisense inside the markup window, so these kinds of methods will actually show up.

SQL Server 2005 Transact SQL Enhancements

Quite a few new features have been addded to SQL Server 2005 in the Transact-SQL area.  Take a look at this article which goes over some of them.
 

Role Providers

One of the new features of ASP.NET 2.0 that I you may have heard about is role providers.  Out of the box there is a Sql Role Provider and a Windows Token Role provider (the access one was removed from beta 2).  You can also of course create your own by doing some inheritance (i.e.: Blue Chip Role Provider). 
 
The role provider you are using is configured in the web.config.  I would include some sample code, but I am pretty sure they changed the entire syntax for configuring it and I am yet to figure it out using the CTPs. 
 
What I am going to talk about today is more about the Roles (System.Web.Security) class and NTLM.  There are also numerous controls that make use of roles, that I will touch on at some point in the future.
 
When using ntlm authentication, the roles class can prove to be quite useful.  It has several member methods that will allow you to determine if the user belongs in a particular Windows NT security group, etc.  This is a lot easier than in the past where you had to use ADSI objects (which basically just used Interop). 
 
The two methods that may be of use when using NTLM are IsUserInRole() and GetRolesForUser().    IsUserInRole will tell you if a user is in a particular Windows NT security group (i.e.: DTG\WWWThrifty).  GetRolesForUser can be used to troubleshoot access issues by returning an array of roles that the user belongs to.
 
An example of GetRolesForUser can be viewed at:
 
This is only a handful of the methods that this class has.  There are a lot more methods that you can use when using a SqlRoleProvider.  These other methods allow you to add users to roles, create new roles, configure the cookie that the roles are stored in, etc.  I'll touch on these more in the future.

Custom Web Events

One of the new features of ASP.NET 2.0 that is less talked about is the health monitoring system.  It allows you log things like failed logins, unhandled exceptions, expired forms authentication tickets, etc.  The new health monitoring system is provider based so you can have it log to the event log or to a sql server out of the box.  Of course you can always create your own provider as well.
 
To create a custom web event, simply create a new class and inherit from WebBaseEvent.  For example, if you wanted to log an event every time a button was clicked (for example, Get a Rate, or Make Reservation), create a class that looks like this.
 
using System;
using System.Web.Management;
 
public class MakeReservationWebEvent : WebBaseEvent
{
     DateTime clickDateTime;
 
     public MakeReservationWebEvent(string message, object source, int eventCode, DateTime myDateTime) : base(message, source, eventCode)
     {
          // assign to classwide variable
          clickDateTime = myDateTime;
     }
 
     // override this method to specify which text is logged
     public override void FormatCustomEventDetails(WebEventFormatter webEventFormatter)
     {
          // log a custom message
          webEventFormatter.AppendLine("Clicked at: " + clickDateTime.ToString());
      }
}
 
Once you have created your custom web event class, you simply need to register it in your machine.config/web.config.
 
<healthMonitoring enable="true">
     <eventMappings>
          <add name="Make Reservation Events" type="MyWebEvent, __code" />
     </eventMappings>
     <rules>
            <!-- log to event log, could also specify SqlWebEeventProvider -->
           <add name="Make Reservation Events" eventName="Make Reservation Events" provider="EventLogProvider" />
     </rules>
</healthMonitoring>
 
Firing the custom event is not as straight forward as you would think.  First you must instantiate your web event and raise it with the base class.  You would put the following in your click event handler:
 
// instantiate your custom web event
MakeReservationWebEvent makeReservationWebEvent = new MakeReservationWebEvent("Reservation Made", null, 101, DateTime.Now);
 
// raise the event to be logged
WebBaseEvent.Raise(makeReservationWebEvent);
 
I think custom web events will prove to be quite powerful and I can see them logging all types of useful information in our applications in the future.

System.Transactions Namespace

There is probably more interest for this on the web services side, since we rarely do that much direct access to a database.  Framework v2.0 makes it really easy to handle transactions.  Transactions make it possible to roll back a series of SQL statements, etc when any one of the statements fail.
 
There are two types of transcations that you will typically deal with Local Implicit and Distributed Implicit (note: there are also Explicit transactions but they seem to be a lot more work and not as convenient.)  A Local Implicit transaction is simply a transaction that talks to only one database.  A Distributed transaction talks to multiple databases at the same time. 
 
The transactions namespace is smart and will automatically use the appropriate transaction broker based on what type of database you are using.  If you are talking to SQL Server 2000 databases, the transactions will be handled through the DTC on the client machine.  When SQL Server 2005 is used, the transactions are handled directly by the SQL Server.
 
Creating a transaction is easy.  Simply create a TransactionScope with a using statement and include your code to execute your sql statements.  When the transaction is complete, tell the TransactionScope, that the commit is ready by setting the Consistent property to true (Note: this property is replaced by the Complete() method in Beta 2).
 
Here is an example of a distributed transaction:
 
using (TransactionScope transactionScope = new TransactionScope())
{
     // create a SqlConnection
     SqlConnection sqlConnection1 = new SqlConnection(connectionString1);
 
     // create a new sqlCommand
     SqlCommand sqlCommand1 = new SqlCommand(someQuery, sqlConnection1);
 
     // open the first connection
     SqlConnection1.Open();
 
     // execute the query
     SqlConnection1.ExecuteNonQuery();
 
     // close the connection
     SqlConnection1.Close();
 
     // open a connection to a second sql server database
 
     // create a SqlConnection
     SqlConnection sqlConnection2 = new SqlConnection(connectionString2);
 
     // create a new sqlCommand
     SqlCommand sqlCommand2 = new SqlCommand(someQuery, sqlConnection2);
 
     // open the first connection
     SqlConnection2.Open();
 
     // execute the query
     SqlConnection2.ExecuteNonQuery();
 
     // close the connection
     SqlConnection2.Close();
 
 
     // tell the scope that the transaction is complete
     transactionScope.Consitent = true;
}
 
The basics of transactions are really quite easy now.  No longer do you have to worry about using Reflection or deriving from ServiceComponent.  This should prove to be quite useful in the future.

Custom Expression Builders

I got a new MSDN magazine in yesterday, so there is actually some new content.  A while back I talked about expressions in ASP.NET (i.e.: <%$ ConnectionStrings:ReservationsConnectionString %>) and I mentioned that there is a way to create your own.   At the time, I didn't know how to do that.  According to Marcus that was "Lame!".  So now I am following up, and showing you how to implement a custom expression builder.
 
As an example (straight from MSDN), if you wanted to display the current version of ASP.NET, we can make a custom expression builder like this:
 
<%$ Version:MajorMinor %>
 
You can create your custom expression logic by building a new class and inheriting from ExpressionBuilder.  In this class you must override the GetCodeExpression method.  This method takes multiple parameters.  The BoundPropertyEntry parameter contains the text to the right of the colon expression.  To access that text you use the Expression property of that parameter.
 
public class VersionExpressBuilder : ExpressionBuilder
{
      public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext content)
      {
             // check to see what the parameter of entry.Expression was
             if (entry.Expression == "MajorMinor")
             {
                   return new CodePrimitiveExpression(String.Format("{0}.{1}", Environment.Version.Major, Environment.Version.Minor));
             else
             {
                  // add more conditionals here
              }  
             }
       }
}
 
To register the expression builder, add the following section to the web.config.
 
<compilation>
     <expressionBuilders>
           <add expressionPrefix="Version" type="VersionExpressionHandler">
     </expressionBuilders>
</compilation>
 
This is obviously a simple example, but you can easily see how we could adopt this to get data from XML files, etc.  This could easily replace our custom label controls and things like that.
 

Accessor Accessibility

Ok, well some people have probably already heard about this one, but content has been getting scarce lately.  Apparently no one works at Microsoft in the month of December.  In C# 2.0, we now have accessor accessibility, which means you can set different levels of protection on the get and set accessors of a property.  This is useful, when maybe you want to be able to get the value of the property outside of a class, but only want to be able to set it from within the class.
 
Here is an example:
 
// notice the entire property is public, but set is protected
public string Name   
   {
      get
      {
         return name;
      }
      protected set   
      {
         name = value;
      }
    }

Global Registration of User Controls

No longer is it necessary to add a line such as the following to every single page:
 
<%@ Register TagPrefix="thrifty" Namespace ="Thrifty.Framework.Web.Navigation" Assembly="Thrifty.Framework" %>
 
Now you can add your reference to every page on the site by simply adding the following to your web.config or machine.config.
 
<configuration>
     <system.web>
            <pages>
                 <registerTagPrefixes>
                     <add
                         tagPrefix="thrifty"
                         namespace="Thrifty.Framework.Web.Navigation"/>
                  </registerTagPrefixes>
             </pages>
     </system.web>
</configuration>
 
This feature isn't terribly exciting but it will make building pages easier in the future and it will allow easy access to every control we have without having to worry if it is registered.

NOTE: This site is migrating to DotNetMafia. For the latest tips on Visual Studio 2008, SharePoint, and MOSS, see Corey's .NET Tip of the Day.