String extensions – Case-insensitive Replace and Contains

The C# string library is pretty comprehensive, but there are a few methods that were left out. Luckily, in C# 3.0 extensions were introduced, which allows developers to seemingly add methods to existing classes. Remember that extensions only work inside the same namespace, so you’ll have to rename “MyNamespace” in the example below.

Two of the missing methods are case-insensitive versions of the methods “Contains” and “Replace”. I do not take credit for writing the methods — I found them on Google and have provided references in the code. I did add the comments to make the overloaded methods match the originals. I also tested them to make sure they behaved like the originals when provided with a null or empty string.

I’m not sure why the .NET team did not provide case-insensitive Replace or case-insensitive Contains, they do it with many other string methods like StartsWith and EndsWith. Hopefully these help.

The case-insensitive Contains code is heavily based on a post on this forum. The case-insensitive Replace code is heavily based on a Code Project comment. Learn more about C# extensions on MSDN.

Please note that I had to butcher some of the XML comments because the code formatter was deleting them. It shouldn’t affect compiling, but you may have to fix some if you want the full Intellisense.

using System;
using System.Text;

namespace MyNamespace
{
    /// <summary>
    /// Overloads the string object and adds case-insenstive options to certain methods
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// Returns a value indicating whether the specified System.String object occurs
        /// within this string.
        /// </summary>
        /// <param name="original">The System.String object to be checked.</param>
        /// <param name="value">The System.String object to seek.</param>
        /// <param name="comparisonType">One of the System.StringComparison values that
        /// determines how this string and value are compared.</param>
        /// <returns>true if the value parameter occurs within this string, or
        /// if value is the empty string (""); otherwise, false.</returns>
        /// <exception cref="System.ArgumentNullException">value is null.</exception>
        static public bool Contains(this string original, string value, StringComparison comparisonType)
        {
            if (original == null)
                throw new NullReferenceException("Object reference not set to an instance of an object.");

            if (value == null)
                throw new ArgumentNullException("value");

            if (String.Empty == value)
                return true;

            return (0 < = original.IndexOf(value, comparisonType));
        }

        /// <summary>
        /// Replaces all occurrences of a specified System.String in this instance
        /// with another specified System.String. < / summary>
        /// <param name="original">The System.String object to be searched.</param>
        /// <param name="oldValue">A System.String to be replaced.</param>
        /// <param name="newValue">A System.String to replace all occurrences of oldValue.</param>
        /// <param name="comparisonType">One of the System.StringComparison values that
        /// determines how this string and value are compared.</param>
        /// <returns>A System.String equivalent to this instance but with all
        /// instances of oldValue replaced with newValue.</returns>
        /// <exception cref="System.ArgumentNullException">oldValue is null.</exception>
        /// <exception cref="System.ArgumentException">oldValue is the empty string ("").</exception>
        static public string Replace(this string original, string oldValue, string newValue, StringComparison comparisonType)
        {
            if (original == null)
                throw new NullReferenceException("Object reference not set to an instance of an object.");

            if (oldValue == null)
                throw new ArgumentNullException("oldValue");

            if (String.Empty == oldValue)
                throw new ArgumentException("oldValue");

            int lenPattern = oldValue.Length;
            int idxPattern = -1;
            int idxLast = 0;

            StringBuilder result = new StringBuilder(original.Length);

            while (true)
            {
                idxPattern = original.IndexOf(oldValue, idxPattern + 1, comparisonType);

                if (idxPattern < 0)
                {
                    result.Append(original, idxLast, original.Length - idxLast);
                    break;
                }

                result.Append(original, idxLast, idxPattern - idxLast);
                result.Append(newValue);

                idxLast = idxPattern + lenPattern;
            }

            return result.ToString();
        }
    }
}

Non-queried multi-value parameters in SQL Server Reporting Services

As a follow-up to my previous post on Easy multi-value parameters in SQL Server Reporting Services, I wanted to point out some information on non-queried, or static multi-value parameters.

For my example, I’m using a parameter named “Time” with choices “Morning”, “Noon”, and “Night”.  The values are M, N, and I respectively.  You can see how I set up the parameter in the following screenshot.

You can accomplish having all the checkboxes selected by default in two ways.  The first way is to pass an object array of values, and the easiest way to do that is to use the Split command to split a string into a string array.  I used =Split(“M,N,I”,”,”) as my default.  I had to provide the second parameter for Split, the delimiter, because the default is space.

The second, and easier method, is to just add a line item for each item you want checked, as demonstrated in this screenshot:

Here is the resulting parameter list, showing all the items selected (same for either method):

Sometimes, you need to display the parameters of your report, perhaps so it could be regenerated later.  You’ll need to print out that object array, so use the opposite of Split, Join.  Below is a textbox with an expression of =Join(Parameters!Time.Label, “, “), which joins the parameter values together with a comma and space separator.

Here is the result of the code, with two parameters selected shown:

If you only put the parameter label in the textbox (i.e. using code =Parameters!Time.Label) then when you display the report, you’ll get the famous Reporting Services #Error message.  You have to use Join in this case.

More on SharePoint “User not found” error with Reporting Services

Following up my initial post on the SharePoint “User not found error with Reporting Services in integrated mode, I wanted to post another reason for the “User not found” error.

If, somewhere in the site author tree, you have user accounts that no longer exist, you will encounter the “User not found” error while viewing the report and browsing the list of shared data sources.

I found two good blog articles about this issue as well as a solution here:

I modified the code a bit to just show the site author without resetting it.  I also changed the code to explicitly dispose of the SharePoint objects.

The utility takes two parameters, the first is the site URL.  If you only pass one parameter, it looks up the site author.  If you pass a second parameter (in the format of DOMAIN\USER), the site author will be reset to the value you supply.

(more…)

6 little things I don’t like about Windows Server 2008 / Vista

I’ve been using Windows Server 2008 since it was released in February.  In general, Server 2008 is a huge improvement over 2003, however, there are a number of little things that annoy me, all of which are also found in Vista.  I plan to talk later about my favorite features in Server 2008, but I’ll start with my pet peeves:

1. Folder icons have been turned sideways

I understand this was done to give a better visual indicator. But who stores real manila folders on their side? Defeats the metaphor if you ask me.

Folder icons are now on their side

Folder icons are now sideways

2. Start menu scrolling is a pain

I don’t like having a fixed size start menu.  Why should I have to scroll to see menu items?  I would like to be able to re-size the menu, but this isn’t really possibly. You can make the menu bigger by bumping up the number of recent items, but you’ll still have to scroll. To adjust the Start menu size, right click on Start menu, choose Properties. Select the top Customize… button. In the Start menu size group, select the Number of recent programs to display option.

Start menu scrolling is a pain

Start menu scrolling is a pain

3. Start menu icon only appears on mouse over

Not having icons on the Start menu for Document, Computer, Network, etc is just annoying. Icons are there for a visual depiction. Having icons apart from the actual item is distracting.  They should either have an icon or not–don’t stick it in as an afterthought.

Start menu icons only appear on mouse over

Start menu icon only appears on mouse over

4. Confusing verbs in the Network and Sharing Center

The Tasks in the Network and Sharing Center are about as confusing as it gets.  If I want to set my IP address for my wireless adapter, which would I choose: Manage wireless networks, Set up a connection, or Manage network connection?  Like a lot of Microsoft products, there are too many ways to do the same thing.  So many similarly worded choices just add to the confusion.

Confusing verbs in the Network and Sharing center

Confusing verbs in the Network and Sharing Center

5.  In Explorer, column resizer is too small

In Explorer windows, Vista/Server 2008 added the filter drop down.  I love this feature but they managed to make resizing columns much more difficult.  The resizer now has just a few pixels where it’s active.  To top it off, when you click on the arrow for the filter, it pops down.  Click it again, and it stays down.  You can’t get it to go away.  Drag the filter arrow and it takes the whole column, so you can re-order them.  Why not just make the filter arrow part of the column resizer?  It makes more sense than it does to re-order the columns and I bet it happens a lot more often.

In Explorer, column resizer is too small

In Explorer, column resizer is too small

6. Not having the “up one folder” button in Explorer.

There is a pretty good bread-crumb navigation in Explorer now.  There is a back button.  But, there is no “up one folder” button, like there used to be.  I know, you can click on the actual item, but having to hunt visually is not nearly as effective as clicking a single button that is always there. At least the keyboard shortcut (backspace) is intact.

Missing the "up one folder" button

Missing the "up one folder" button

The old "UP" button - where did you go?

The old "UP" button - where did you go?

Page 2 of 512345