Developer Blog
Articles about Using Microsoft Developer Tools

Create an RSS Feed in ASP.NET

Monday, January 18, 2010 4:52 PM by jonwood

Recently, it occurred to me that one of my websites would probably benefit from an RSS feed. However, I really didn’t understand what RSS feeds were. I understood the basic purpose but really had no clue as to how they worked. With words like “syndication” being tossed around when describing RSS feeds, I had imagined it involved some sort code that continually sent data to some mystical location.

Fortunately, understanding RSS feeds is very easy, and creating your own RSS feed in ASP.NET is a breeze. RSS stands for Really Simple Syndication. It provides a standard for you to make information available to anyone who wants to request your feed. One of my sites is a shareware site and I thought a feed would allow users to stay in contact with my site and make it more likely that they would return. Moreover, an RSS feed allows them to do this without signing up or even giving me their email address.

These days, it’s getting easier for users to use feeds because more and more software is starting to support them. For example, when you enter the URL of a feed into Microsoft Internet Explorer, the information is now formatted specifically for feeds. Microsoft Live Mail also has direct support for feeds. There are also a number of websites that can help you to subscribe to and view RSS feeds.

An RSS feed is simply an XML file on your site that conforms to the RSS specification. Of course, since feeds are meant to be constantly updated, you would normally want to generate this file on-the-fly when it is requested. And, of course, ASP.NET makes this very easy to do.

Listing 1 shows my feed file. This is a normal, every day ASPX file and what you see makes up the entire contents of the file. The first thing to notice is the OutputCache declaration on the second line. When you use OutputCache, requests for this file within the given duration will simply return a copy of the previous results. The duration is in seconds, so if two requests for this file occur within two minutes, the code will not run again for the second request. Instead, ASP.NET will simply return the same data that was returned for the first request. Since the page runs potentially lengthy code and makes a potentially substantial hit on the database, this ensures the site doesn’t get bogged down under heavy traffic.

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ OutputCache Duration="120" VaryByParam="none" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="SoftCircuits" %>
<script runat="server">
  
  /// <summary>
  /// Create RSS Feed of newest submissions
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  protected void Page_Load(object sender, EventArgs e)
  {
    // Clear any previous response
    Response.Clear();
    Response.ContentType = "text/xml";
    //
    XmlTextWriter writer = new XmlTextWriter(Response.OutputStream,
      Encoding.UTF8);
    writer.WriteStartDocument();
    // The mandatory rss tag
    writer.WriteStartElement("rss");
    writer.WriteAttributeString("version", "2.0");
    // The channel tag contains RSS feed details
    writer.WriteStartElement("channel");
    writer.WriteElementString("title", "File Parade's Newest Submissions");
    writer.WriteElementString("link", "http://www.fileparade.com");
    writer.WriteElementString("description",
      "The latest freeware and shareware downloads from File Parade.");
    writer.WriteElementString("copyright",
      String.Format("Copyright {0} SC Web Group. All rights reserved.", DateTime.Today.Year));
    // File Parade image    
    writer.WriteStartElement("image");
    writer.WriteElementString("url",
      "http://www.fileparade.com/Images/logo88x31.png");
    writer.WriteElementString("title",
      "File Parade Freeware and Trialware Downloads");
    writer.WriteElementString("link",
      "http://www.fileparade.com");
    writer.WriteEndElement();
    // Objects needed for connecting to the SQL database
    using (SqlDataReader reader = DataHelper.ExecProcDataReader("GetRssFeed"))
    {
      // Loop through each item and add them to the RSS feed
      while (reader.Read())
      {
        writer.WriteStartElement("item");
        writer.WriteElementString("title",
          EncodeString(String.Format("{0} {1} by {2}",
          reader["Title"], reader["Version"],
          reader["Company"])));
        writer.WriteElementString("description",
          EncodeString((string)reader["Description"]));
        writer.WriteElementString("link",
          String.Format("http://www.fileparade.com/Listing.aspx?id={0}",
          reader["ID"]));
        writer.WriteElementString("pubDate",
          ((DateTime)reader["ReleaseDate"]).ToShortDateString());
        writer.WriteEndElement();
      }
    }
    // Close all tags
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteEndDocument();
    writer.Flush();
    writer.Close();
    // Terminate response
    Response.End();
  }
  protected string EncodeString(string s)
  {
    s = HttpUtility.HtmlEncode(s);
    return s.Replace("\r\n", "<br />\r\n");
  }
</script>

Listing 1: RSS Feed

Next are my declarations to import the needed namespaces. Nothing special here—just the declarations needed for database access. Note that this code won’t run for you as listed. It includes my SoftCircuits namespace, which contains some in-house routines for the database. You’ll need to replace this with your own database code. This makes sense since you’ll be returning your own data.

The core of the code is placed in the Page_Load event handler. As you know, this code is called when the page is first requested. The first step is to clear the response of any previously output content. Remember, we are creating an XML file and we don’t want any other content to be returned. Next, we set some headers so that the user agent can see what type of content we are returning.

From here, we go ahead and create an XmlTextWriter and attach it to our output stream, and we can start creating our output. We start with some mandatory RSS tags—these are need to identify our content as an RSS file. Next, we add some mandatory tags that describe our channel. This provides additional, descriptive information about our content. Next, I add some optional tags, which specify a small image and related data.

After that, we can finally start to output our actual data. My code uses an in-house method called DataHelper.ExecProcReader, which calls a stored procedure to obtain my data. You will need to replace this with your own code to return whatever data you are syndicating. My routine simply returns a SqlDataReader and I loop through each row in the data it returned.

Note that I perform some modifications to my text fields before writing them. In my case, this text is submitted from various authors and I don’t want them to include their own HTML markup. So I call HtmlEncode, which causes markup to appear as it was written instead of allowing it to modify the layout, formatting, or creating links. I then insert my own markup by placing <br /> wherever there is a newline. This ensures newlines will appear for the user. I should point out that WriteElementString() will HTML-encode the string being written. This prevents markup from disturbing the XML markup. Note that data will be HTML-decoded when it is read. So you only need to mess with this if you want to tweak the data you are returning.

We then flush the XML writer for good measure, and terminate our response. Again, we are creating an XML file and this last step prevents any other output from accidently being included in the response.

If you’re like me, you may be a little surprised how easy this really is. To allow someone to check your feed, you simply provide them with the URL to this page. Using software that supports feeds, they can have instant access to your data in a convenient format. And, of course, are more likely to return to your site when they need more information.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   ASP.NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Implementing Word Wrap in C#

Sunday, January 10, 2010 1:44 PM by jonwood

The .NET platform makes it easy to send emails from your code. However, it was bothering me the other day that my emails had no word wrap.

In most cases, modern email readers will word wrap when email lines are too long. But there are still some email readers around that won’t. The industry standard is to wrap email lines, limiting their length to about 65-75 characters. So I decided it was worth implementing word wrap in my code.

As rich as it is, the .NET platform does not appear to have any routines for implementing word wrap. I found some sample code online but, while the code was fairly simple (which is good), I didn’t think it was very efficient.

The .NET platform provides many routines for parsing text and extracting substrings, etc. but these generally involve allocating and moving lots of memory. So my approach was to write simple C# code that would word wrap the code without unnecessarily allocating additional objects.

Of course, I will need a new string in order to save my results. And since I’ll be building that string line-by-line, I used the StringBuilder class for this. The StringBuilder class allows you to more efficiently build a string without allocating new strings each time you make a change. Listing 1 is the code I came up with.

protected const string _newline = "\r\n";
/// <summary>
/// Word wraps the given text to fit within the specified width.
/// </summary>
/// <param name="text">Text to be word wrapped</param>
/// <param name="width">Width, in characters, to which the text
/// should be word wrapped</param>
/// <returns>The modified text</returns>
public static string WordWrap(string text, int width)
{
  int pos, next;
  StringBuilder sb = new StringBuilder();
  // Lucidity check
  if (width < 1)
    return text;
  // Parse each line of text
  for (pos = 0; pos < text.Length; pos = next)
  {
    // Find end of line
    int eol = text.IndexOf(_newline, pos);
    if (eol == -1)
      next = eol = text.Length;
    else
      next = eol + _newline.Length;
    // Copy this line of text, breaking into smaller lines as needed
    if (eol > pos)
    {
      do
      {
        int len = eol - pos;
        if (len > width)
          len = BreakLine(text, pos, width);
        sb.Append(text, pos, len);
        sb.Append(_newline);
        // Trim whitespace following break
        pos += len;
        while (pos < eol && Char.IsWhiteSpace(text[pos]))
          pos++;
      } while (eol > pos);
    }
    else sb.Append(_newline); // Empty line
  }
  return sb.ToString();
}
/// <summary>
/// Locates position to break the given line so as to avoid
/// breaking words.
/// </summary>
/// <param name="text">String that contains line of text</param>
/// <param name="pos">Index where line of text starts</param>
/// <param name="max">Maximum line length</param>
/// <returns>The modified line length</returns>
public static int BreakLine(string text, int pos, int max)
{
  // Find last whitespace in line
  int i = max - 1;
  while (i >= 0 && !Char.IsWhiteSpace(text[pos + i]))
    i--;
  if (i < 0)
    return max; // No whitespace found; break at maximum length
  // Find start of whitespace
  while (i >= 0 && Char.IsWhiteSpace(text[pos + i]))
    i--;
  // Return length of text before whitespace
  return i + 1;
}

Listing 1: Word Wrap Code

The code starts by extracting each line from the original text. It does this by locating the hard-coded line breaks. Note that my code searches for carriage return, line feed pairs (“\r\n”). Some platforms may only use “\n” or other variations for new lines, but the carriage return, line feed pair works in most cases on Windows systems. You can change the _newline constant if you want the code to look for something else.

The code then copies each line to the result string. If a line is too long to fit within the specified width, then it is further broken into smaller lines. Each time through the loop, if the line needs to be broken, the BreakLine method is called to locate the last white space that fits within the maximum line length. This is done to try and break the line between words instead of in the middle of them.

While the string object provides the LastIndexOf() method, which could be used to locate the last space character, I manually coded the loop myself so that I could use Char.IsWhiteSpace() to support all whitespace characters defined on the current system. If no whitespace is found, the line is simply broken at the maximum line length.

As each line is broken, that the code removes any spaces at the break. This avoids trailing spaces on the current line or leading spaces on the next line. Although there is normally only one space between each word, the code tries to correctly handle cases where there might be more.

As each new line is created, a carriage return, line feed pair is also added to separate each line. Note the special case for handling when the line is empty, in which case we just write the carriage return, line feed pair.

There’s nothing complex about this code, but I took a little extra time to make it efficient. Note that the word wrap is based on the number of characters and not the display width. If you were, for example, word wrapping text output to the screen or printer, the code should probably test different line lengths measured on a device context in order to determine the display length.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   C# .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Implement Accelerators in a Dialog-Based Application

Tuesday, June 09, 2009 6:57 AM by jonwood

One of the options you have when creating an MFC application is to make your application dialog-based. This is one of the options in the MFC Wizards.

Dialog-based applications are simply an application where the main window is a dialog box. Applications that need to display a bunch of controls in the main window are considerably easier to implement as a dialog-based application.

In addition, you can also add a menu to your dialog box, which can complete a sophisticated dialog-based application. A menu can be added by simple choosing the menu resource ID in the properties window for the dialog box. But if your menu has accelerators (hotkeys) you’ll notice that they don’t work. In this article, I’ll describe getting accelerators to work in a dialog box.

The discussion below assumes you have created a dialog box with a menu, that you’ve also created an accelerator resource with hotkeys for one or more commands in your dialog box menu, and that you’ve defined handlers for those commands.

In your main application class (not the dialog box class), define the following member variable.

HACCEL m_hAccelTable;

Listing 1: Add variable to main application class.

Next, initialize this variable in your main application class’s InitInstance() method. You may want to initialize it after the basic MFC initialization code but be sure to initialize it before the main dialog box is displayed. Again, this is in your main application class and not in your dialog box class.

BOOL CMyApp::InitInstance()
{
  // ...
  m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
    MAKEINTRESOURCE(IDR_ACCELERATOR1));
  // ...
}

Listing 2: Initialize variable in InitInstance().

Note that this code assumes the ID of your accelerator is IDR_ACCELERATOR1. You’ll need to change it if you are using a different resource ID.

Next, override ProcessMessageFilter in your main application class. Again, this is in your main application class and not in your dialog box class.

BOOL CMyApp::ProcessMessageFilter(int code, LPMSG lpMsg)
{
  if (code >= 0 && m_pMainWnd && m_hAccelTable)
  {
    if (::TranslateAccelerator(m_pMainWnd->m_hWnd, m_hAccelTable, lpMsg))
      return TRUE;
  }
  return CWinApp::ProcessMessageFilter(code, lpMsg);
}

Listing 3: Override ProcessMessageFilter().

And that’s all there is to it. Assuming you have the menu and accelerator resources implemented and associated with your dialog box, and you have handlers for the commands, the accelerators should now work.

I’m not sure why this change is even necessary and couldn’t easily find out. At first glance, it sure seems like this trivial amount of code should be implemented in the base MFC classes. But this approach is simple and should work for any dialog box in your application (that includes a menu and accelerator resource).

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   C++/MFC
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Confirm Before Deleting Grid Item

Tuesday, May 12, 2009 4:17 AM by jonwood

When deleting an item in one of the ASP.NET grids, it would be nice to ask the user to confirm this is what they really meant to do. After all, it is very easy to mouse click somewhere by accident. And what would be even nicer is if this confirmation takes place on the client (browser) instead of requiring yet another round trip to the server.

Fortunately, this task is very easy to do. As you might expect, the answer is to use javascript. In some cases, setting up javascript on an ASP.NET page can get a little involved. However, a simple script can be added using the OnClientClick property, which is available with many ASP.NET controls.

Listing 1 shows part of the ASP.NET code for a GridView control. This code includes an ItemTemplate that defines a delete button and includes some confirmation javascript in the OnClientClick property.

<asp:GridView ID="GridView1" runat="server" />
  <Columns>
    <asp:TemplateField>
      <ItemTemplate>
        <asp:LinkButton ID="lnkDelete" runat="server"
          CausesValidation="false" 
          CommandName="DeleteItem"
          Text="Delete" CommandArgument='<%# Bind("ItemID") %>'
          OnClientClick="return confirm('Delete this item?');">
        </asp:LinkButton>
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>

Listing 1: Javascript to confirm deleting a GridView item.

This simple javascript calls confirm(), which returns true if the user selects Yes. The code associated with posting back the form and deleting the item only executes if this script returns true.

So, that’s a very simple technique that is easy to implement and works very well. And because it uses javascript, it doesn’t perform the postback to the server unless the user confirms they really do want to delete the grid item.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   ASP.NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Validating Credit Card Numbers

Tuesday, May 12, 2009 2:17 AM by jonwood

When using ASP.NET to process online credit card orders, it is a good idea if you can perform some sort of validation on the credit card number before submitting it to your processor. I recently had to write some code to process credit card orders and thought I’d share a bit of my code.

Fortunately, credit card numbers are created in a way that allows for some basic verification. This verification does not tell you if funds are available on the account and it certainly doesn’t tell whether or not the person submitting the order is committing credit card fraud. In fact, It’s possible that the card number is mistyped in such a way that it just happens to pass verification. But it does catch most typing errors and reduces bandwidth by catching those errors before trying to actually process the credit card.

To validate a credit card number, you start by adding the value of every other digit, starting from the right-most digit and working left. Next, you do the same thing with the digits skipped in the first step, but this time you double the value of each digit and add the value of each digit in the result. Finally, you add both totals together and if the result is evenly divisible by 10, then the card has passed validation.

Of course, this would be clearer with a bit of code and Listing 1 shows my IsCardNumberValid method.

public static bool IsCardNumberValid(string cardNumber)
{
  int i, checkSum = 0;
  // Compute checksum of every other digit starting from right-most digit
  for (i = cardNumber.Length - 1; i >= 0; i -= 2)
    checkSum += (cardNumber[i] - '0');
  // Now take digits not included in first checksum, multiple by two,
  // and compute checksum of resulting digits
  for (i = cardNumber.Length - 2; i >= 0; i -= 2)
  {
    int val = ((cardNumber[i] - '0') * 2);
    while (val > 0)
    {
      checkSum += (val % 10);
      val /= 10;
    }
  }
  // Number is valid if sum of both checksums MOD 10 equals 0
  return ((checkSum % 10) == 0);
}

Listing 1: Validating a credit card.

The IsCardNumberValid method assumes that all spaces and other non-digit characters have been stripped from the card number string. This is a straight forward task but Listing 2 shows the method I use for this.

public static string NormalizeCardNumber(string cardNumber)
{
  if (cardNumber == null)
    cardNumber = String.Empty;
  StringBuilder sb = new StringBuilder();
  foreach (char c in cardNumber)
  {
    if (Char.IsDigit(c))
      sb.Append(c);
  }
  return sb.ToString();
}

Listing 2: Removing all non-digit characters from a credit card number.

You will also be able to reduce bandwidth if you can avoid trying to submit a card that is not supported by the business. So another task that can be useful is determining the credit card type.

public enum CardType
{
  Unknown = 0,
  MasterCard = 1,
  VISA = 2,
  Amex = 3,
  Discover = 4,
  DinersClub = 5,
  JCB = 6,
  enRoute = 7
}
// Class to hold credit card type information
private class CardTypeInfo
{
  public CardTypeInfo(string regEx, int length, CardType type)
  {
    RegEx = regEx;
    Length = length;
    Type = type;
  }
  public string RegEx { get; set; }
  public int Length { get; set; }
  public CardType Type { get; set; }
}
// Array of CardTypeInfo objects. Used by GetCardType() to identify credit card types.
private static CardTypeInfo[] _cardTypeInfo =
{
  new CardTypeInfo("^(51|52|53|54|55)", 16, CardType.MasterCard),
  new CardTypeInfo("^(4)", 16, CardType.VISA),
  new CardTypeInfo("^(4)", 13, CardType.VISA),
  new CardTypeInfo("^(34|37)", 15, CardType.Amex),
  new CardTypeInfo("^(6011)", 16, CardType.Discover),
  new CardTypeInfo("^(300|301|302|303|304|305|36|38)", 14, CardType.DinersClub),
  new CardTypeInfo("^(3)", 16, CardType.JCB),
  new CardTypeInfo("^(2131|1800)", 15, CardType.JCB),
  new CardTypeInfo("^(2014|2149)", 15, CardType.enRoute),
};
public static CardType GetCardType(string cardNumber)
{
  foreach (CardTypeInfo info in _cardTypeInfo)
  {
    if (cardNumber.Length == info.Length && Regex.IsMatch(cardNumber, info.RegEx))
      return info.Type;
  }
  return CardType.Unknown;
}

Listing 3: Determining a credit card’s type.

Listing 3 is my code to determine a credit card’s type. I’m a big fan of table-driven code, when it makes sense, and so I created an array of CardTypeInfo objects. The GetCardType() method simply loops through this array, looking for the first description that would match the credit card number being tested. As before, this routine assumes all non-digit characters have been removed from the credit card number string.

The main reason I like table-driven code is because it makes the code simpler. This results in code that is easier to read and modify. GetCardType() returns a value from the CardType enum. CardType.Unknown is returned if the card number doesn’t match any card descriptions in the table.

Writing code to process credit cards involves a number of issues that need to be addressed. Hopefully, this code will give you a leg up on addressing a couple of them.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   C# .NET | ASP.NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Shallow and Deep Object Copying

Sunday, April 12, 2009 1:23 PM by jonwood

In .NET, class objects are reference types. Assigning one object variable to another object variable does not copy that object, it simply causes both object variables to reference the same object.

Sometimes, a copy is required. For example, maybe two routines need to start with the same data but then change that data independently from each other. Copying the data ensures that changes made by one routine will not impact the data being used by the other routine.

When using .NET, two types of copies are possible: shallow and deep. In the case of a shallow copy, a new object is created and each member from the original object is assigned to the corresponding member of the new object. In the case of value members, this is a copy in the truest sense. However, with objects that contain reference members, this does not produce a true copy.

One example of a reference type is a string. When you assign one string variable to another, both variables will reference the same string data. The characters of the strings are not truly copied. So if a class contains reference members, a shallow copy does not create a true copy of all class members.

For many cases, a shallow copy is sufficient. Note that strings are immutable and cannot be changed. When you create a shallow copy of an object that contains strings, and then modify a string in the new object, that would create a new string and would not have any impact on the original string in the original object. Note that other data types such as arrays, class objects, and arrays of class objects can be quite a bit more complicated than strings.

A deep copy is when a copy is created that contains none of the original data. A true copy of each member is created. A deep copy doesn’t need to do anything special with members that are value types. But for reference data types, the new object must reference copies of that data instead of the original data.

There is nothing unique about how either method of copying an object are performed. Consider listing 1. This code declares a class called MyClass, and then shows a short method called Test that performs both a shallow and a deep copy using that class object.

protected class MyClass
{
   public int i;
   public int j;
   public string message;
}
private void Test()
{
   MyClass mc1;
   MyClass mc2;
   mc1 = new MyClass();
   mc1.i = 5;
   mc1.j = 10;
   mc1.message = "Hello, World!";
   // Shallow copy
   mc2 = new MyClass();
   mc2.i = mc1.i;
   mc2.j = mc1.j;
   mc2.message = mc1.message;
   // Deep copy
   mc2 = new MyClass();
   mc2.i = mc1.i;
   mc2.j = mc1.j;
   mc2.message = String.Copy(mc1.message);
}

Listing 1: Shallow and deep copying of an object.

The shallow copy does nothing special. It simply assigns each member from one object to the other. For value members, the deep copy uses the same code. However, for the one reference member, message, the code must create a copy of the string data. (Note that addition steps would be required to perform a deep copy with objects that include reference members with references to additional objects, such as class members, arrays, etc.)

Now that I’ve hopefully explained the difference between a shallow and a deep copy, let’s take a look at some of the tools the .NET frameworks provide to perform these tasks.

protected class MyClass : ICloneable
{
   public int i;
   public int j;
   public string message;
   public object Clone()
   {
      return MemberwiseClone();
   }
}
private void Test()
{
   MyClass mc1 = new MyClass();
   mc1.i = 5;
   mc1.j = 10;
   mc1.message = "Hello, World!";
   // Shallow copy
   MyClass mc2 = (MyClass)mc1.Clone();
}

Listing 2: Using MemberwiseClone() to perform a shallow copy.

Listing 2 uses MemberwiseClone() to perform a shallow copy. MemberwiseClone() is protected and so cannot be called directly from Test. Instead, I’ve modified MyClass to implement the ICloneable interface and implemented the one ICloneable method, Clone. (Normally, ICloneable is associated with a deep copy but I use it here to implement a shallow copy.) The Test method calls this new method to perform the shallow copy. Since Clone() returns type object, a type cast is required.

To perform a deep copy, Listing 3 also implements the ICloneable interface. This listing just modifies the code in the Clone() method to perform a deep copy.

protected class MyClass : ICloneable
{
   public int i;
   public int j;
   public string message;
   public object Clone()
   {
      MyClass mc = new MyClass();
      mc.i = i;
      mc.j = j;
      if (message != null)
         mc.message = String.Copy(message);
      return mc;
   }
}
private void Test()
{
   MyClass mc1 = new MyClass();
   mc1.i = 5;
   mc1.j = 10;
   mc1.message = "Hello, World!";
   // Deep copy
   MyClass mc2 = (MyClass)mc1.Clone();
}

Listing 3: Using ICloneable to perform a deep copy.

The actual code in the Clone() method should be familiar by now. The main advantage to implementing it this way is that it is implemented as part of the class, where it can easily be modified and called from any where in your application.

Nothing too complex here, although the concept behind a shallow and deep copy can be confusing to some. Hopefully, I’ve shown some light on this topic and demonstrated how you might approach the issue using .NET.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   C# .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

BackgroundWorker.ReportProgress is Asynchronous

Sunday, April 12, 2009 12:12 PM by jonwood

I never noticed this before but the BackgroundWorker.ReportProgress method returns before the control’s ProgressChanged event has completed. It may return before the ProgressChanged event has even started!

For those not familiar with the BackgroundWorker control, this control simplifies creating a worker thread, especially for the purpose of keeping the user interface responsive while the worker thread performs a lengthy process.

One issue it simplifies relates to the fact that the worker thread cannot directly access the form or its controls because those objects were created by the UI thread. Instead, code running in the worker thread can call the control’s ReportProgress method, which raises the control’s ProgressChanged event. You can pass information to ReportProgress that describes the current state of the lengthy process, and the handler for the ProgressChanged can use that data to display it to the user in your form controls.

I had been using this approach for a lengthy operation that could run for days. A lot was going on so I was passing an instance of a custom class that contained various bits of progress information. But, at one point, I saw that the progress information being displayed was not correct. On further inspection, I could see that my worker thread was updating the progress information object before the ProgressChanged event handler had a chance to display that information.

It is very easy to get caught up with multi-threading issues as some things are just not very intuitive. When I called the ReportProgress method, I had just assumed that it would not return until the ProgressChanged event had completed. But I was wrong.

Thinking about it, the way this control works makes sense. If, instead, the worker thread was blocked until the event had returned, some of the benefits of a worker thread would be lost as one thread would be shut down during that time. Also, note that the ProgressChanged method is overloaded. One version simply takes an integer argument. Since integers are passed by value, there would be no reason to suspend the worker thread when using this version of the ProgressChanged method.

The other version takes an object in addition to the integer argument. That’s the version I was using. Since class objects are passed by reference, changes to this data made in the worker thread would be reflected in the same object being used in the ProgressChanged event.

At first thought, I wondered if maybe I should resolve this by blocking the worker thread somehow until the event had run to completion. But, as I’ve already pointed out, this eliminates some of the advantage of having a worker thread in the first place. A much simpler solution is to simply make a copy of my progress class object. This way, the worker thread can modify its copy as needed while the ProgressChanged event is reading its copy, perhaps both at the same time.

Note that I only required a “shallow” copy. In the case of value members, a shallow copy will create a true copy of those members. In the case of reference members, the copy is actually a reference to the same object. The only reference members in my case were strings. Since strings are immutable and cannot be changed, if my code updated one of these members, that would create a new string and not affect the original one referenced in the object passed to ReportProgress.

protected class ProgressInfo
{
   public int current;
   public int total;
   public string message;
   public object Clone()
   {
      return (ImportStatus)MemberwiseClone();
   }
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
   ProgressInfo info = new progressInfo();
   info.total = 1000;
   for (info.current = 0; info.current < info.total; info.current++)
   {
      info.message = String.Format("Processing item {0}",
         info.current + 1);
      backgroundWorker1.ReportProgress(0, info.Clone());
      //
      // Further processing on this item
      //
   }
}

Listing 1: Passing copy of object to BackgroundWorker.ReportProgress

Listing 1 shows some sample code. The ProgressInfo class declares a Clone() method, which calls MemberwiseClone(). MemberwiseClone() performs a shallow copy of the object. Note that this method is protected and, therefore, can only be called from a method of the class (or a derived class). This is why it was necessary to create the additional, public, “wrapper” method in my class, which my worker thread can call.

Using this code, my ProgressChanged event handler can take its time displaying the progress data and will not be affected by my background worker thread making changes to its copy of that data at the same time.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   C# .NET
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

What are Kilobytes, Megabytes, Gigabytes, Etc?

Friday, April 03, 2009 5:16 AM by jonwood

Okay, we are all familiar with kilobytes, megabytes, gigabytes and the like. Most of us know that a kilobyte is approximately a thousand bytes. And that is accurate enough for most purposes. But what if you need to need to deal with these numbers a bit more accurately?

A kilobyte is exactly 1,024 bytes. So why not 1,000 bytes? Computers use binary to generate numbers. So memory addresses are naturally a power of two. 1,000 is not a power-of-two number, but 1,024 is.

Just as a million is a thousand times a thousand, a megabyte is a kilobyte times a kilobyte, or 1,048,576 bytes. Again, close enough to a million for many purposes but not exactly a million.

Here are the values for some power-of-two numbers.

Number Abbreviation Value
1 Kilobyte KB 1,024 Bytes
1 Megabyte MB 1,048,576 Bytes
1 Gigabyte GB 1,073,741,824 Bytes
1 Terabyte TB 1,099,511,627,776 Bytes
1 Petabyte PB 1,125,899,906,842,624 Bytes
1 Exabyte EB 1,152,921,504,606,846,976 Bytes

    I was working on an MFC application recently and needed to define some large numbers that I felt would be more efficient if the numbers were a power of two. I ended up defining the following C++ macros.

    #define KB(n) (((UINT64)0x400)*((UINT64)(n))) 
    
    #define MB(n) (((UINT64)0x100000)*((UINT64)(n))) 
    
    #define GB(n) (((UINT64)0x40000000)*((UINT64)(n))) 
    
    #define TB(n) (((UINT64)0x10000000000)*((UINT64)(n))) 
    
    #define PB(n) (((UINT64)0x4000000000000)*((UINT64)(n))) 
    
    #define EB(n) (((UINT64)0x1000000000000000)*((UINT64)(n)))

    Macros to make it easy to declare large power-of-two numbers.

    These macros make it easy to exactly declare a large number. For example, if I want to define four gigabytes, I can simply say GB(4).

    Nothing complicated here. But if you need to make use of these numbers, it’s nice to have a table of actual values along with some handy helper macros.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Tags:  
    Categories:   General | C++/MFC
    Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

    Good Bye IE6—And Good Riddance!

    Monday, January 26, 2009 10:18 AM by jonwood

    Well, that’s it as far as I’m concerned. I have a laptop that runs Windows XP and, until today, Internet Explorer version 6. However, Windows Update is now automatically updating XP systems to Internet Explorer version 7, which I’ve just installed.

    I can only assume Windows Update is doing this now due to recent security holes found in IE6. After being infected with a major virus recently, upgrading to IE7 seemed like a good idea. But as an ASP.NET developer, there are far larger considerations involved.

    Internet Explorer 6 is notorious for not following the established Web standards that pretty much every other browser is following. In my view, this has made Website development, particularly layout and CSS, an absolutely nightmare! There have been many times I’ve spent hours getting layout exactly as I want it only to find it does not appear as expected in IE6. In fact, many books I have on CSS design have entire chapters devoted to IE6 and its unique set of layout quirks.

    As with most of their products, Microsoft wanted to make their browser exceptional by doing their own thing. But this just doesn’t work in the browser world. There have to be standards in order for the largest number of browsers to work with the largest number of Websites. That’s not to say all other browsers are identical in their rendering of Web content—they’re not. But IE6 was the odd one out with a large majority of issues.

    So, until now, I’ve continued to maintain a computer running IE6 in order to be able to test my sites with this browser. But now that Windows Update is urging users to upgrade, I’m going to give up on this browser. Of course, not everyone will upgrade. There are always users who will resist changes like this for as long as possible. But I expect this development to mean that the number of IE6 users will drop significantly. And I’m willing to take advantage of this and no longer work to ensure my sites appear correctly for the diminishing number of users who use this browser.

    With IE6 out of the picture, the biggest offender of not following Web standards is now IE7. But IE7 is quite a bit better than IE6. And, perhaps more significant, IE8 is about to be released. IE8 presented Microsoft with some difficult decisions. On the one hand, Microsoft realized that the latest Web standards could no longer be ignored. But on the other hand, if they came out with a fully compliant browser, they would break compatibility with previous versions, causing some pages that looked fine with IE6 to no longer appear correctly.

    There was considerable discussions about whether IE8 should require a flag in the HTML code to tell it to use the new compliant mode, otherwise, it would default to being compatible with prior versions. This would allow both new and old sites to appear correctly.

    I fought strongly against this approach. This opens up a whole can of worms. And, from a Web developer’s viewpoint, it’s critical to get everyone in line using the current standards and end the chaos we have now, which was caused in large part by the noncompliance of IE6. Although I have not played with IE8 or heard the latest on this issue, I did hear at one point that the decision was to make IE8 standards-compliant by default.

    If this becomes the final decision, I applaud Microsoft for making this hard choice. They will take a hit if they come out with a browser that, by default, produces different rendering of some Web pages than previous versions of IE. But I think this is in the best interest the industry. And, in my book, not having to worry about IE6 anymore is a good thing.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Tags:  
    Categories:   ASP.NET
    Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

    Implementing Non-ASP.NET Posts in ASP.NET

    Thursday, January 22, 2009 6:14 AM by jonwood

    When interfacing with some resource on the Web, you are sometimes provided with a little snippet of HTML code. For example, to insert a PayPal button on your Website, PayPal provides HTML code that may look something like this.

    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    
      <input type="hidden" name="cmd" value="_xclick">
    
      <input type="hidden" name="business" value="bob@domain.com">
    
      <input type="hidden" name="lc" value="US">
    
      <input type="hidden" name="item_name" value="Widget">
    
      <input type="hidden" name="amount" value="100.00">
    
      <input type="hidden" name="currency_code" value="USD">
    
      <input type="hidden" name="bn"
    
        value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">
    
      <input type="image"
    
        src="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
    
        border="0" name="submit" alt="">
    
      <img alt="" border="0"
    
        src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1"
    
        height="1">
    
    </form>

    HTML code to insert PayPal button

    This snippet defines a <form> and several <input> tags, including a submit button. When the submit button is clicked, the items in the form are posted to the URL specified in the action attribute of the <form> tag. The target URL can then inspect the values of those <input> tags and perform the required operation.

    However, you may find that such snippets don’t work correctly when inserted into an ASP.NET page. The main problem is that ASP.NET pages already define a form. In order for ASP.NET’s post-back mechanism to work, all the controls are placed within a <form> tag. Since HTML doesn’t allow nested <form> tags, inserting code like that shown above into an ASP.NET page causes problems.

    There are a number of possible approaches to resolving this. Let me start with a couple that I think are less than ideal. The first approach is to simply move the inserted HTML code after the ending </form> tag of the ASP.NET form. Although you cannot nest <form> tags, it is okay to include multiple, non-nested <form> tags on the same page.

    The result of this is that the page now has two separate <form> tags and you’ll find this generally works as expected. However, the problem here is that you lose some ASP.NET functionality. For example, the inserted HTML code comes after your ASP.NET form and so it is not really embedded within your ASP.NET content. And if you are using master pages, you cannot do this in content pages because everything in a content page is placed inside of the <form> tag defined in the master page.

    The second approach is kind of an ugly hack and is shown below.

    protected void btnPayPal_Click(object sender, ImageClickEventArgs e)
    
    {
    
      System.Web.HttpContext.Current.Response.Clear();
    
      System.Web.HttpContext.Current.Response.Write("<html><head>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "</head><body onload='document.form1.submit()'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<form action='https://www.paypal.com/cgi-bin/webscr' " +
    
        "name='form1' method='post'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='cmd' value='_xclick'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='business' " +
    
        "value='bob@domain.com'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='lc' value='US'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='item_name' value='Widget'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='amount' value='100.00'>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='currency_code' value='USD'>
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='hidden' name='bn' " +
    
        "value='PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest'>
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<input type='image' " +
    
        "src='https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif' " +
    
        "border='0' name='submit' alt=''>");
    
      System.Web.HttpContext.Current.Response.Write(
    
        "<img alt='' border='0' " +
    
        "src='https://www.paypal.com/en_US/i/scr/pixel.gif' " +
    
        "width='1' height='1'>");
    
      System.Web.HttpContext.Current.Response.Write("</form>");
    
      System.Web.HttpContext.Current.Response.Write("</body></html>");
    
      System.Web.HttpContext.Current.Response.End();
    
    }

    Ugly hack to perform non-ASP.NET postback

    This code runs in response to the user clicking a button named btnPayPal. It dynamically creates an HTML page and then serves it to the user’s browser. The page created duplicates the form in our first listing but adds an onload attribute to the page’s <body> tag that causes the form to be submitted as soon as it loads and the user never sees this temporary page.

    This is definitely an ugly hack. And, while it works, it has some problems. The main problem is if, after running the code, the user presses the Back button in their browser, the browser will reload this temporary page, which will cause the same action to happen again, which definitely has the potential to cause some nasty problems.

    After exploring both of these options, I finally settled on a third approach that seems more straight forward and doesn’t seem to have any major problems. Beginning with ASP.NET 2.0, buttons have a property called PostBackUrl, which can be used to have that button post back to a page other than the page that contains the button.

    At first glance, this didn’t seem helpful. ASP.NET buttons are designed to post back to ASP.NET pages. And I wanted to post back to an non-ASP.NET page. However, the post-back mechanism is the same in both cases. If we post back to a non-ASP.NET page, we’re going to send a lot of additional data—all of the form items on our ASP.NET form—to the target page. But, as long as their is no conflicting item names, which is unlikely, this really isn’t a problem.

    Armed with this knowledge then, we can rewrite our original code block and insert it into an ASP.NET page.

    <input type="hidden" name="cmd" value="_xclick">
    
    <input type="hidden" name="business" value="bob@domain.com">
    
    <input type="hidden" name="lc" value="US">
    
    <input type="hidden" name="item_name" value="Widget">
    
    <input type="hidden" name="amount" value="100.00">
    
    <input type="hidden" name="currency_code" value="USD">
    
    <input type="hidden" name="bn"
    
      value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">
    
    <asp:ImageButton ID="ImageButton1" runat="server"
    
      ImageUrl="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
    
      PostBackUrl="https://www.paypal.com/cgi-bin/webscr" />

    PayPal button inserted into ASP.NET page

    I’ve removed the <form> tag from this code. We don’t need it since our ASP.NET form already defines a <form> tag. I’ve removed the <img> and submit <input> tags and I’ve replaced them with an ImageButton. I set the ImageButton’s ImageUrl property to the same PayPal button image used in the original code and, finally, I set the PostBackUrl property to the URL specified in the action attribute of the <form> tag in our original HTML code.

    The result is that, when the ImageButton is clicked, the entire form is posted to the PayPal URL. As I mentioned before, this includes all our other ASP.NET values, including the page’s ViewState data. But the ViewState data is encrypted and the PayPal site will only look at those values it is interested in.

    The result is that I’ve inserted a PayPal button at any location within my ASP.NET form, I’m still able to make use of all ASP.NET features, PayPal gets all the values it needs to do its job, and there is no funny business if the user happens to hit the browser’s Back button from the PayPal site.

    Currently rated 5.0 by 3 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Tags:   ,
    Categories:   ASP.NET
    Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed