Validate at least one option is selected in radio button list on Webform

On a webform there is a radiobutton list. The user must select at least one of the options for the form to be valid.

<div>
	<asp:Label ID="Label37" runat="server" Text="Is Sales Item:" AssociatedControlID="rblSaleItem" />
	<asp:RadioButtonList ID="rblSaleItem" runat="server" ClientIDMode="Static" TabIndex="36"
		RepeatDirection="Horizontal" RepeatLayout="Flow" CssClass="checkbox-list">
		<asp:ListItem Text="Yes" Value="1"></asp:ListItem>
		<asp:ListItem Text="No" Value="0"></asp:ListItem>
	</asp:RadioButtonList>
	<asp:CustomValidator ID="IsSaleItemCustomValidator" runat="server" Text="Is Sales Item: selection is required"
		Display="Dynamic" ClientIDMode="Static" ClientValidationFunction="IsSalesItemValidator"
		OnServerValidate="IsSalesItemValidation" ValidationGroup="FORMGROUP" CssClass="field-validation-error"></asp:CustomValidator>
</div>

Here we have the javascript validation. The radiobutton list and validator are in the same div element, so from the validation control triggered we go up to the parent to find the radiobutton list. Each radio button in the list is tested to see if it is selected.

// Javascript client side validation
function IsSalesItemValidator(sender, args) {
    args.IsValid = false;

    $("#" + sender.id).parent().find(".checkbox-list").find(":radio").each(function () {
        if ($(this).is(":checked")) {
            args.IsValid = true;
            return;
        }
    });
}

On the server side the validation works in a similar way.

// C# Server side validation
protected void IsSalesItemValidation(object source, ServerValidateEventArgs args)
{
    // has a sale item check box been selected
    foreach (ListItem li in rblSaleItem.Items)
    {
        if (li.Selected)
        {
            args.IsValid = true;
            break;
        }
    }
}

I actually do not like the idea of iterating through the radiobutton list to find if one is checked. Normally the radiobutton lists are quite short on a page so it is probably not a big overhead, but it is too old school lazy coding for my liking. In .Net3.5 the Enumerable class was introduced in the System.Linq namespace. Unsing the Enumerable.Cast method we can construct linq queries to retrieve the selected item from the radiobutton list instead of iterating all the items.

protected void IsSalesItemValidation(object source, ServerValidateEventArgs args)
{
    var selectedItem = (from li in rblSaleItem.Items.Cast<ListItem>()
                        where li.Selected == true
                        select li).FirstOrDefault();
    /*
    // Alternatively if you prefer inline linq
    var selectedItem = rblSaleItem.Items.Cast<ListItem>()
                        .Where(item => item.Selected == true).FirstOrDefault();
    */
    
    args.IsValid = SelectedItem != null && SelectedItem.Selected;
}

Using the FirstOrDefault() method will return null if there are not selected items in the radiobutton list. If we were to use the First() method an InvalidOperationException would be thrown if there are no elements that meet the query conditions.
It is safe to use the Cast method in this situation because it is guaranteed all the items in the collection are of the ListItem type. If the Cast method was used on a collection containing different objects an InvalidCastException will be thrown. If the collection object itself is null an ArgumentNullException will be thrown.

Using Enumerable.Intersect to find items in two lists

On a recent post where I discussed using LINQ to find all items in one list which also exist in another list (intersection) using linq expressions, a comment was posted suggesting I look into using Enumerable.Intersection.  So this is it.

First of all a straight forward example, finding the intersect of two lists of integers

Console.WriteLine("Number intersect...");
var lista = new List<int> { 1, 44, 56, 87, 23 };
var listb = new List<int> { 20, 23, 1 };
var numbers = lista.Intersect<int>(listb);
numbers.ToList().ForEach(i => Console.WriteLine(i));

The result of the Intersect() method returns two integers because they exist in both lists.

1
23

And a simple example using strings.

Console.WriteLine("String intersect...");
var listx = new List<string> { "Ben", "Phil", "Mary", "Paula", "Peter", "Samuel" };
var listy = new List<string> { "samuel", "Paula", "Ben" };
var names = listx.Intersect<string>(listy, StringComparer.OrdinalIgnoreCase);
names.ToList().ForEach(n => Console.WriteLine(n));

As StringComparer.OrdinalIgnoreCase is being passed as the second parameter to the Intersect() method three matches are being found, if case was not ignored the ‘samuel’ string in listy would not be included in the results.

Ben
Paula
Samuel

In the next examples I will be using a product class and two lists of products. Notice how productA and productB are declared and instantiated outside of the array initialisations.

public class Product
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}
.
...
.
var productA = new Product { Code = "CD5", Name = "Paint", Category = "Decorating" };
var productB = new Product { Code = "FG9", Name = "Ladder", Category = "Access" };
Product[] listm = {new Product{Code="AM1",Name="Bucket", Category="Decorating"},
                    new Product{Code="AM3",Name="Brush", Category="Decorating"},
                    productA,
                    productB,
                    new Product{Code="MN4",Name="Table", Category="Furniture"}
                    };
Product[] listn = {new Product{Code="CV6",Name="Brush", Category="Decorating"},
                    productA,
                    productB,
                    new Product{Code="Am3",Name="Brush", Category="Decorating"},
                    };

Calling the Intersect method on lists of objects in this way will only return those objects that are the same instances.

Console.WriteLine("object intersect...");
Console.WriteLine("IEnuerable.Intersect<TSource>...");
var products = listm.Intersect(listn);
products.ToList().ForEach(p => Console.WriteLine(p.Code));

So by default, the results only include the two pre-instantiated objects because, as well as being in both lists, they are the same instance.

CD5
FG9

There are two more scenarios I have been considering:
1. Get a list of all product codes in both lists.
2. Get a list of all product objects where the product code is in both lists.

I initially solved the first scenario in the following way. Note how the Select() method is used to retrieve the product codes so the Intersect() method is comparing two lists of string rather than objects. also note the use of the StringComparer to ignore text case.

var codesLINQ = listm.Select(a => a.Code).Intersect(listn.Select(b => b.Code), StringComparer.OrdinalIgnoreCase);
codesLINQ.ToList().ForEach(p => Console.WriteLine(p));

As we are comparing two lists of strings, the output includes the AM3 product code because it exists in both lists even though it is not the same object instance and we are ignoring case.

AM3
CD5
FG9

The second scenario was solved using a Where() method to retrieve the objects from listm that match the product code in listn. Note again this is ignoring case.

var productsLINQ = listm.Where(a => listn.Any(b => string.Compare(b.Code, a.Code, true) == 0));
productsLINQ.ToList().ForEach(p => Console.WriteLine(p.Code));

The output to the console for this example will be the same as the previous example, the only difference is that the productsLINQ variable contains the product objects not just the product codes.

In these two scenarios LINQ has been used in some form but it is possible to get the desired results without LINQ. As these two scenarios above are so similar their solution is similar too, so I am going to focus on solving the second one without using LINQ. To solve this problem we could change the product class could implement the IEquatable generic interface or to implement the IEqualityComparer generic interface in a helper class. The advantage of the latter is that your product class better follows the Single Responsibility Principle in that it will only need to change if your product info changes, not if the comparison criteria changes. For additional information check the MSDN documentation here. Firstly the IEquatable implementation.

public class Product : IEquatable<Product>
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }

    public bool Equals(Product other)
    {
        //Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal.
		return string.Compare(Code, other.Code, true) == 0;

		// alternative comparison code.
		//return Code.ToUpper().Equals(other.Code.ToUpper());
    }

    // If Equals() returns true for a pair of objects
    // then GetHashCode() must return the same value for these objects.

    public override int GetHashCode()
    {
        //Get hash code for the Code field.
        int hashProductCode = Code.ToUpper().GetHashCode();

        //Calculate the hash code for the product code.
        return hashProductCode;
    }
}

By implementing the IEquatable interface we can now control how the objects are compared. This implementation only compares the product code.
Calling the Intersect() method does not change from earlier.

var products = listm.Intersect(listn);
products.ToList().ForEach(p => Console.WriteLine(p.Code));

The products variable holds the product objects that match the comparison code. In the earlier example when the Intersect() method was called before the IEquatable interface was implemented we got two product in the result. Now with the interface implemented there are three product products in the match.

AM3
CD5
FG9

The next example (the better example IMHO) shows how to implement the IEqualityComparer interface in a ProductComparer class.
Notice how the Code and Name properties are being compared to identify a match.

public class Product
{
    public string Code { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product x, Product y)
    {
        //Check whether the objects are the same object.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether the products' properties are equal.
        return x != null && y != null
            && x.Code.ToUpper().Equals(y.Code.ToUpper())
            && x.Name.ToUpper().Equals(y.Name.ToUpper());

		// Alternative comparison code
		/*return x != null && y != null
            && string.Compare(x.Code, y.Code, true) == 0
            && string.Compare(x.Name, y.Name, true) == 0;*/
    }

    public int GetHashCode(Product obj)
    {
        //Get hash code for the Name field if it is not null.
        int hashProductName = obj.Name == null ? 0 : obj.Name.ToUpper().GetHashCode();

        //Get hash code for the Code field.
        int hashProductCode = obj.Code.ToUpper().GetHashCode();

        //Calculate the hash code for the product.
        return hashProductName ^ hashProductCode;
    }
}

When calling the Intersect() method you pass an instance of the ProductComparer as a parameter.

var products = listm.Intersect(listn, new ProductComparer());
products.ToList().ForEach(p => Console.WriteLine(p.Code));

As well as single responsibility, another advantage to implementing the IEqualityComparer interface over the IEquatable interface is you could have multiple ProductComparer classes with different criteria e.g. one that compares the product code and one that compares the code and Name properties. You decide which one you pass to the Intersect() method.

Find all items in list which exist in another list using linq

I just wanted to go through a few examples of how to retrieve all the items in a list, that also exist in another list. This is one of those useful techniques which you may not need very often and so this post will act as a reminder.

To start with we need arrays.

var lista = new List<string>(){"one","two","three","four","five","six","seven"};
var listb = new List<string>(){"One","fortyfour","six"};

These examples are designed on the principle that we want to retrieve all the values from lista which also exist in listb. This can be done by using an explicit linq join,

result = from a in lista
    join b in listb on a.ToLower() equals b.ToLower()
    select a;

Although it could be written on a single line, this type of query is usually written over multiple lines for clarity. The same result could be achieved as below

result = lista.Where(a => listb.Any(b => a.ToLower() == b.ToLower()));

One method is not necessarily better than the other and I am sure there are a number of other ways the same result could be achieved.
I find using the string.Compare() method saves from having to keep converting to lower case.

var result = lista.Where(a => listb.Any(b => string.Compare(a,b,true) == 0));

If you were to output the contents of the result variable from both the above examples you would see they all produce the same result (based on the original array contents)

one
six

The last example will retrieve all the items from lista where the text of the item is contained in the text of an item in listb.

var result = lista.Where(a => listb.Any(b => b.Contains(a)));

Note that the Contains method is case sensitive so the result would be

four
six

because listb has an item that contains the text ‘four’, which is the text of an item in lista. Also both lists have an item with the same text ‘six’.

Reversing a string using the Reverse Method in LINQ

A while back I wrote this post on how to use an extension method to reverse a string of text.  The method simply iterated each character in reverse order appending the character to a StringBuilder object, as shown below.

string oldstring = "England";
StringBuilder newString = new StringBuilder();
for (int i = oldString.Length - 1; i >= 0; i--)
{
    newString.Append(oldString[i]);
}

There is another way to reverse a string. Enter the LINQ Reverse method which “Inverts the order of the elements in a sequence” the keyword here is sequence. The result of calling the method is “A sequence whose elements correspond to those of the input sequence in reverse order.”
Again the word sequence. As a string object is s sequence of characters the result of the following statement

"Hello".Reverse();

will be IEnumerable, a sequence of characters because the method will see the input as a sequence of characters.
LINQ Reverse method in LINQPad
The desired output is to have a single string, so at this point we could iterate the sequence of characters using For loop and appending each character to a StringBuilder like in the previous example.

var oldString = "Hello".Reverse();
StringBuilder newString = new StringBuilder();
for (int i = 0; i < oldString.Length; i++)
{
    newString.Append(oldString[i]);
}

But I personally do not see any advantages in doing it this way as there will be additional processing from introducing the extra Reverse() method call.
What we can do here is use the string.Join method to concatenate the character sequence together. The signature of the Join method is string.Join(string, string[]). The first parameter is the separator which is only included in the returned string only if value has more than one element. The second parameter is an array that contains the elements to concatenate, Our sequence of characters needs to be somehow converted to an array.
So to reverse a string we need only a bit of extra LINQ and single line of code **drum roll please**

string.Join(string.Empty,
    "Hello".Reverse().Select(s => s.ToString()).ToArray())

Now, I am not recommending any one particular way. I have not compared memory or processor efficiencies between these techniques. What is plain is the difference in the number of lines required.