Stephen Sulzberger’s Blog

May 26, 2008

Use C# ?? null coalescing operator for parsing request query string parameters

Filed under: .net,asp.net,C#,Web development — Stephen @ 7:16 pm

I’m a big fan of succinct code, especially when it comes to satisfying requirements that are ultimately trivial but redundant. That being said, I think the following is the best way to parse query string parameters:

    string sParam = "t"; 
    string sResult = string.Empty; 

    sResult = (Request.QueryString[sParam] ?? "").Trim();

    if (sResult != "")
    {
      // Do something
    }

If the request string param is null, the string returns “”. If the request string param has a value, we snag it and Trim() to ensure that we get what we want and nothing else (this is important, especially since users can toy with the param values and send values with unexpected extra spaces). The idea here is to encapsulate as many “checks” into a simple, quick parse to ensure that you don’t have to back track and validate anything (insofar as handling null or empty data). Notice, also, that I use the Trim() method outside of the “coalescing” routine – this is because if the Request.QueryString[] call returned null, Trim() would throw an object reference exception.

Some other methods you might use for accomplishing the same thing:

Example 1

      string sParam = "t";
      string sResult = string.Empty;
      
      if ((Request.QueryString[sParam] != null) && (Request.QueryString[sParam].Trim() != ""))
      {
        sResult = Request.QueryString[sParam].Trim();
      }

      if (sResult != "")
      {
        // Do something
      }

Example 2

      string sParam = "t";
      string sResult = string.Empty;      
      
      sResult = (null != Request.QueryString[sParam]) ? Request.QueryString[sParam].Trim() : "";

      if (sResult != "")
      {
        // Do something
      }

Example #1 and #2 will each give the same end result and functionality as the null coalescing approach sketched above, but at any rate they contain a lot of redundancy. The null coalescer is the easiest approach of the proffered bunch, I think. 

For more information on the C# null coalescing operator and some other interesting uses (e.g. using it with LINQ), check out: http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx

April 2, 2008

asp.net: Handle comments in xml files

Filed under: asp.net,C#,Web development,xml — Stephen @ 7:29 pm

A small point, but asp.net’s XmlDocument doesn’t seamlessly handle xml comments when iterating through sub elements of an XmlNodeList. It’d be nice if XmlDocument didn’t read comments in the first place (I’d venture to say that xml comments aren’t meant to be read by compiled code), but I suppose it might be useful on some occasions to have the Load() method return everything in an xml doc. 

Not a big deal, but remember to handle comments explicitly any time an editable data file is consumed using the XmlDocument object.

For example, if expecting an xml document such as:

<?xml version="1.0" encoding="utf-8" ?>
<items>
  <item>
    <itemValue>value1</itemValue>
    <!--<itemValue>value2</itemValue>-->
    <itemValue>value3</itemValue>
  </item>
  <item>
    <!--<itemValue>value1</itemValue>-->
    <itemValue>value2</itemValue>
    <itemValue>value3</itemValue>
  </item>
</items>

The following approach (or similar) would need to be used in order to prevent the commented areas from being processed as bona fide elements:

    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.Load(HttpContext.Current.Server.MapPath(@"~\App_Data\file.xml"));

    XmlNodeList nodeRoot = xmlDoc.GetElementsByTagName("item");

    for (int i = 0; i < nodeRoot.Count; i++)
    {
      XmlNodeList objNodes = nodeRoot[i].ChildNodes;

      foreach (XmlNode node in objNodes)
      {
        if (node.NodeType == XmlNodeType.Comment)
          continue;

        // Do something.
      }      
    }

In this case, “objNodes” actually contains 3 elements for each item – 2 elements with NodeType Element and 1 element with NodeType Comment. If this is not handled properly in the iterations, it is possible for the code (or general routine) to fail supposing that an element is commented out with the intention for it to not be processed.

For more information: http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.value.aspx

February 8, 2008

asp.net: vs_targetSchema meta tag (and others) no longer required

Filed under: asp.net,Web development — Stephen @ 3:52 pm

Recently I was migrating legacy asp.net pages (v1.1) to 2.0 and noticed the following code snippet in every header:

  <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1" />
  <meta name="CODE_LANGUAGE" content="C#" />
  <meta name="vs_defaultClientScript" content="JavaScript" />
  <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5" />

Apparently the tags had been used in the past for design-time html support/validation. They’re no longer required if using Visual Studio 2005 or higher.

Some more good info at: http://www.velocityreviews.com/forums/t97952-can-i-remove-this-meta-tag.html

January 20, 2008

asp.net: Modify Request.QueryString

Filed under: .net,asp.net,C# — Stephen @ 4:30 pm

Suppose you needed to modify the query string passed in a given URL before redirecting to another (or even the same) page. For example, imagine you needed to take:

/default.aspx?name1=value1&name2=value2&color=red

and turn it into something like:

/default.aspx?name1=valueX&name2=valueY&colorcode=red

I’ve seen this done with loops, new URI’s, and so on to get around the query string read-only “problem”, but most implementations like these are fairly arduous, not to mention error-prone. Given all of the idiosyncrasies involved with the Request.QueryString object (e.g. is read-only, is a modified version of the NameValueCollection object, etc.), I still think the the following approach is the best bet:

using System.Collections.Specialized;

public partial class ModifyQueryStringExample : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // Create a new (editable) NameValueCollection using the existing (read-only) collection
    NameValueCollection objNewValueCollection = HttpUtility.ParseQueryString(Request.QueryString.ToString());
    objNewValueCollection.Set("name1", "valueX");
    objNewValueCollection.Set("name2", "valueY");
    objNewValueCollection.Add("colorcode", objNewValueCollection.Get("color"));
    objNewValueCollection.Remove("color");

    string sRedirect = Request.Url.AbsolutePath;
    string sNewQueryString = "?" + objNewValueCollection.ToString();

    sRedirect = sRedirect + sNewQueryString;

    Response.Redirect(sRedirect, true);
  }
}

Some notes:

  1. All other parameters passed in by the original query string will be carried over untouched. For example, if the original query string also included something like “id=1234&status=1”, these values would persist into the new redirect even while the other name/value pairs have been modified.    
  2. The NameValueCollection Set() method allows nulls, so it will work regardless of whether or not the key you’re looking for actually exists. If the key exists, the value will be appended accordingly. If the key does not exist, it will be added with the appropriate value. This time around I chose to use the Add() method for readability since I know for a fact that this routine will always be adding a key (“colorcode”) rather than appending one.
  3. All NameValueCollection methods that use a text compare are case-insensitive, as per msdn: http://msdn2.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection.namevaluecollection.aspx 
  4. The NameValueCollection ToString() method automatically inserts “=”/”&” characters for you when/where appropriate. The NameValueCollection instance returned by HttpUtility.ParseQueryString is an HTTPValueCollection (a specialized NameValueCollection type), so its ToString() method will automatically insert “=”/”&” characters for you where appropriate. Although this is undoubtedly a nice feature, one can’t help but mention that the surprisingly convenient behavior just described is not immediately obvious given the msdn documentation at http://msdn.microsoft.com/en-us/library/system.web.httputility.parsequerystring.aspx. Nevertheless, the implementation is made clear by evaluating any NameValueCollection.ToString() against an HTTPValueCollection.ToString(). The former will return the object’s string representation (‘System.Collections.Specialized.NameValueCollection’) while the latter, of course, will provide a legitimate name/value collection with the applicable field-value separators. Interestingly, the only way to get an HTTPValueCollection instance in the first place is to use HttpUtility.ParseQueryString. No doubt a quirky matter. For further discussion on the issue, visit http://msmvps.com/blogs/paulomorgado/archive/2008/07/15/make-the-httpvaluecollection-class-public-and-move-it-to-system-dll.aspx               

January 6, 2008

Converting VB to C# (and vice versa)

Filed under: asp.net — Stephen @ 7:32 am

I’ve come across a ton of examples and tutorials both online and in print that insist on using and/or providing VB script and nothing more. This really isn’t a big deal considering asp.net makes it super easy to work with consolidated and (for the most part) commonly named directives, methods, and libraries. Even when you don’t have the benefit of common naming, syntax is usually easy to deal with (or, at least, manageable) on a read-only basis when the general flow/concept is made obvious by the context.

But let’s face it – VB just looks ugly. For cases where I have to stare at it for a long time, I like using the free tool at developer fusion to convert VB to C# (incidentally it also converts C# to VB). It’s not perfect, but handy. Probably one of the better convertors out there. 

Blog at WordPress.com.