Blog Home  Home Feed your aggregator (RSS 2.0)  
Scott Klueppel's Blog - Tuesday, August 30, 2005
.NET Discourse
 
# Friday, August 12, 2005

Yesterday, S. Somasegar, Corporate Vice President, Developer Division (Microsoft) shared some fantastic news, in his blog, about a new language enhancement in C# 2.0. In addition to Generics, Anonymous Methods, Iterators, and Partial Types, we will now have nullable types. Also, more details on MSDN about nullable types

Friday, August 12, 2005 8:58:43 PM (Eastern Standard Time, UTC-05:00)  #    Comments   .NET Framework | C#  | 
# Tuesday, August 09, 2005

I have read too many articles showing the connection being opened and closed around a DataAdapter Fill() as in the code below. It does no harm, but it not necessary.

Don't do this...

SqlCommand command = new SqlCommand("usp_MyQuery_Select", this._con);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet ds = new DataSet();
try
{
   this._con.Open(); //unnecessary
   adapter.Fill(ds);
}
finally
{
   this._con.Close(); //unnecessary
}

Do this...

SqlCommand command = new SqlCommand("usp_MyQuery_Select", this._con);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adapter.Fill(ds);

If you track SqlDataAdapter's Fill() method in Lutz Roeder's .NET Reflector, you will see that it ends up at DbDataAdapter's FillFromCommand() method. FillFromCommand() opens and closes the connection in a try-finally block. Making this unnecessary in your own code.

Disassembled from Reflector

private int FillFromCommand(object data, int startRecord, int maxRecords,
   string srcTable, IDbCommand command, CommandBehavior behavior)
{
   IDbConnection connection1 = DbDataAdapter.GetConnection(command, "Fill");
   ConnectionState state1 = ConnectionState.Open;
   if (MissingSchemaAction.AddWithKey == base.MissingSchemaAction)
   {
      behavior |= CommandBehavior.KeyInfo;
   }
   int num1 = 0;
   try
   {
      try
      {
         DbDataAdapter.QuietOpen(connection1, out state1);
         using (IDataReader reader1 = command.ExecuteReader(
            behavior | CommandBehavior.SequentialAccess))
         {
            if (data is DataTable)
            {
               return this.Fill((DataTable) data, reader1);
            }
            return this.Fill((DataSet) data, srcTable, reader1, startRecord, maxRecords);
         }
      }
      finally
      {
         DbDataAdapter.QuietClose(connection1, state1);
      }
   }
   catch
   {
      throw;
   }
   return num1;
}

Tuesday, August 09, 2005 8:59:40 PM (Eastern Standard Time, UTC-05:00)  #    Comments   .NET Framework | C#  | 
# Friday, August 05, 2005

Most developers cringe when they hear the words "Coding Standards." A developers coding style defines them. Their style has been molded over the years into what it is today. Telling a developer that their way is not the "right way" is difficult and sometimes taken personally.

Coding standards are, however, an important part of every project. Deciding on coding standards often happens too late when there is too much code in too many different styles. It is important to every developer to have and appreciate standards because we will "inherit" someone elses code. It would be nice if we could read it.

I recently got the chance to review David McCarter's 53-page book titled "VSDN Tips & Tricks .NET Coding Standards." I loved it! It combines coding standards from Microsoft and other sources (not to mention common sense) into one easy-to-read "guide." Its focus is on Visual Studio .NET 2003 with v1.1 of the Framework. That doesn't mean that you Beta 2 snobs can't read it! It provides C# :) and VB :( examples and covers a variety of topics from indentation and word choice to event and exception handling.

I have seen most of the suggested standards in various other white papers and on MSDN. It's a great book to compare against your company or personal coding standards. Not everything in this book will make sense to every shop. Personally, I found only a few items that I don't already use (one of which being the use of Event Accessors instead of using public event member variables.)

Definitely worth reading. Find out more at http://www.vsdntips.com

Friday, August 05, 2005 9:00:17 PM (Eastern Standard Time, UTC-05:00)  #    Comments   .NET Framework | C#  | 
# Saturday, July 23, 2005

Dmitri Khanine and Phil Carrillo author this fine article on Javascript RPC. Finally, an article that mentions separation of business and presentation logic, and implementing MVC in ASP.NET. We need more patterns and practices discussions, and a lot less "look what I can do" articles.

MSDN Article: Life without Refresh

Saturday, July 23, 2005 9:01:30 PM (Eastern Standard Time, UTC-05:00)  #    Comments   AJAX | ASP.NET | Javascript  | 
# Saturday, June 04, 2005

Devloping an application using the System.Web.Mail.SmtpMail class to send email should not be as difficult as it always is. http://www.systemwebmail.com has a detailed and helpful collection of possible fixes for the dreaded "Could not access 'CDO.Message' Object" Exception. The one I most recently experienced was not listed. We thought it could be a relaying perrmission or something related to setting the SmtpServer name. It turned out to be a Windows 2003-specific problem related to Fixed Identity Impersonation for high security (isolated) applications using a low-privilege user account specific to the application.

The exception you see, almost always the useless excpetion, "Could not access 'CDO.Message' Object", does not help you to troubleshoot. As you can see in the code below, generated using Lutz Roeder's .NET Reflector, called by SmtpMail.Send(), the real exception is never thrown. It will throw the "Could not access 'CDO.Message' Object" exception no matter what exception was caught.

internal object CallMethod(object obj, string methodName, object[] args)
{
   object obj1;
   try
   {
      obj1 = SmtpMail.LateBoundAccessHelper.CallMethod(
         this.LateBoundType, obj, methodName, args);
   }
   catch (Exception exception1)
   {
      throw new HttpException(HttpRuntime.FormatResourceString(
         "Could_not_access_object", this._progId), exception1);
   }
   return obj1;
}

The best advice given by http://www.systemwebmail.com is to loop through all of the InnerExceptions thrown when the useless exception is thrown. This will allow you to see the true exception and determine how to fix the problem.

In Windows 2003, you can have each application run in its own application pool using an application-specific user account. Depending on the privileges and group memberships of this user account, it may or may not have the correct permissions to be able to send mail using the machine's SMTP server. To send mail, the user account needs to have write permissions on the directory named C:\inetpub\mailroot\Pickup. With those permissions, System.Web.Mail (.NET wrapper around CDOSys.dll) will create a .eml file in that directory. The mail gets sent when the SMTP service, with SYSTEM privileges, sees this file and sends the email.

If granting the necessary permissions is not possible for your application's user account, you can bypass System.Web.Mail's default CDO send method, using the Pickup directory, altogether. You can modify the mail message's configuration fields to set the values used by CDO, regardless of the values set by System.Web.Mail.

You can send the mail message by going through the smtp port instead of the pickup directory (default). Change the sendusing configuration field from 0 (default - pickup directory) to 1 (port).

mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing", 1);

If you still cannot send email, try using other CDO configuration fields to bypass the System.Web.Mail settings. Here are some other configuration fields. I would try them in this order:

// smtpauthenticate values (2=NTLM, 1=Basic, 0=None)
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1);
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", 25);
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver", mailServer);
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", username);
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", pw);
mailMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout", 10);


Of course, all of this is only possible if you are using .NET Framework 1.1. The Fields property of the MailMessage class was not exposed in version 1.0 of the framework.

Saturday, June 04, 2005 9:02:18 PM (Eastern Standard Time, UTC-05:00)  #    Comments   ASP.NET | C#  | 
# Saturday, October 16, 2004

DropDownLists within a Repeater appear to lose or forget which item is selected before the page loads. This is not the case. Dynamically created DropDownLists inside of a Repeater create a rare obstacle. The SelectedItem is not being lost or forgotten. It only appears that way because the OnDataBinding event for the DropDownList is being called twice. Only when the RepeaterItem containing the DropDownList calls its own DataBind method is the data actually bound to the DropDownList. Consider the following code:

// UsingDropDownLists.aspx
115 <asp:Repeater id="rptOne" runat="server" OnItemCreated="rptOne_ItemCreated"/>
116  <ItemTemplate>
117    <asp:Literal id="litQuestion" runat="server"/>
118    <asp:DropDownList id="ddlResponse" runat="server"/>
119    <br/>
120  </ItemTemplate>
121 </asp:Repeater>

// UsingDropDownLists.aspx.cs
211 protected void rptOne_ItemCreated(object sender, RepeaterItemEventArgs e)
212 {
213   if(e.Item.DataItem != null)
214   {
215     MyClass myClass = sender as MyClass;
216     (e.Item.FindControl("litQuestion") as Literal).Text = myClass.Question;
217     DropDownList ddl = e.Item.FindControl("ddlResponse") as DropDownList;
218     ddl.DataSource = GetResponseList(myClass.AvailableResponses);
219     ddl.Items.FindByValue(myClass.Response).Selected = true;
220     ddl.DataBind();
221     ddl.SelectedIndex = e.Item.ItemIndex%(ddl.Items.Count-1); //Random
222   }
223 }

Here is the sequence of events:
  1. Page_Load
  2. Data Retrieval/Bind Data to Repeater
  3. Repeater's ItemCreated event fires for each RepeaterItem
  4. Data Retrieval/Bind Data to DropDownList
  5. OnDataBinding is fired from the DropDownList's DataBind() (line 220). However, if you watch in debug mode, you will see that the DropDownList has no ListItems yet.
  6. DropDownList's SelectedIndex is chosen (line 221). Although, at this point, the DropDownList still has no ListItems. The SelectedIndex call falls on deaf ears.
  7. RepeaterItem's DataBind method performs an actual DataBind on the DropDownList. There are no selected items at this point.

RepeaterItem inherits from Control. If you look at Control's DataBind() method in Lutz Roeder's .NET Reflector, you will see that it performs a DataBind on each of its child controls. 

public virtual void DataBind()
{
   this.OnDataBinding(EventArgs.Empty);
   if (this._controls != null)
   {
      string text1 = this._controls.SetCollectionReadOnly("Parent_collections_readonly");
      int num1 = this._controls.Count;
      for (int num2 = 0; num2 < num1; num2++)
      {
         this._controls[num2].DataBind();
      }

      this._controls.SetCollectionReadOnly(text1);
   }
}

From this, we can see three things.

  1. The only safe time to choose the SelectedItem is after the binding of all objects within the Repeater. A perfect place to do this is in the RepeaterItem's PreRender or in the Repeater's PreRender. You have access to the same bound object from RepeaterItem.DataItem, and can find the DropDownList and choose the SelectedIndex, SelectedValue, or ddl.Items.FindByValue(response).Selected = true;
  2. The DataBind() call (line 220) is completely unnecessary and leads the programmer to believe that it has actually bound the data. This is untrue. Again, in debug mode, you will see that by line 221, there are still zero ListItems in ddl.Items.
  3. The same obstacle will arise for all Controls derived from ListControl. This includes CheckBoxList, DropDownList, ListBox, and RadioButtonList. The same solution will apply to these controls within a Repeater.

Saturday, October 16, 2004 9:03:32 PM (Eastern Standard Time, UTC-05:00)  #    Comments   ASP.NET | C#  | 
# Monday, October 11, 2004

This is my personal site.  Register your Jeep into the Got Jeep Gallery for the world to see.  See pictures from off-roading trips and events.  Read installation and maintenance articles.  Got Jeep?

Monday, October 11, 2004 9:04:30 PM (Eastern Standard Time, UTC-05:00)  #    Comments   General  | 
Copyright © 2008 Scott Klueppel. All rights reserved.