Radio button within a repeater problem

Recently I was developing a system to create tests and test questions.  For these tests our client wanted multiple choice questions.  To implement this I decided to have a list of textboxes for the answer text, and a radio button for each textbox to select the correct answer.   I knew that a RadioButtonList couldn’t have anything other than a radio button and text, so I went with a repeater.

<asp:Repeater ID="rptRadios" runat="server">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li>
            <asp:RadioButton ID="rbRadio" runat="server" GroupName="RadioGroup" />
            &nbsp;
            <asp:TextBox runat="server" ID="txtRadio"></asp:TextBox>
        </li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>

Doing it this way caused the group name of each radio button to be inconsistent, because of the repeater. After a while of researching and not finding any good solutions I decided to try changing the group name of the radio buttons using jQuery.

$("input:radio").attr('name', 'RadioGroup');

That gave me the radio button functionality that I wanted, but it prevented me from getting the selected radio button on postback. So I decided to just implement the radio button functionality manually.

var radios = $("input:radio");
radios.click(function() {
     radios.removeAttr('checked');
     $(this).attr('checked', 'checked');
     return true;
});

Which gave me the correct functionality and I could still get the selected radio button and textbox on postback. Probably not the most elegant solution, but I couldn’t find any other way to do it.

Also I needed to make sure at least one of the radio buttons was selected so I added a CustomValidator that called a javascript function.

function ValidateRadioButtons(sender, args) {
     args.IsValid = $("input:radio:checked").size() > 0;
}
Advertisements

Registration Code Generation

I was recently assigned the task of creating unique registration codes for a product. The requirements were as follows:

  • 12 digits long
  • 3 groups of 4, separated by hyphens
  • No duplicates, of course
  • Easy for anyone to recognize and enter

I began by using the GUID.NewGuid() method. This gave me a long hexadecimal string of random characters between 0 and 9, a-f. By taking various substrings from this and then making sure there were no collisions with any existing registration code, I could have a very randomized registration code generator.

However, upon further reflection–and recalling difficulty I myself have had in the past trying to enter the right codes–I came up with the following issues:

  • It’s really difficult to distinguish between a zero and the letter “O”. The people trying to enter the registration code would not know that it was generated from a GUID that only had the letters A-F, so I wanted to eliminate this confusion for the user.
  • It’s really difficult to distinguish between the lowercase “L” -“l” and the number one (“1”) in some fonts.
  • You probably want to avoid some obvious combinations in the code like “KKK” or “666”. Even though our code would contain groups of 4 characters, it seemed best to still avoid those.

We opted to make the registration code all upper case. We also decided to change the ones and zeroes to “h’s” and “k’s. We skipped “g” since it goes “below the line” in the lower case version. We also skipped “i” since that can look like a lowercase “l” or a “1” if, for whatever reason, the printing isn’t clear. So, with all of that, here’s the code:

public string CreateRegistrationCode()
{            
    string code = "";
    while (code == "") //repeat until you don't get a collision
    {
         //replace zeroes and ones to eliminate confusion between o's and L's.  
         //Also get rid of the hyphens in the GUID
         string newGuidString = Guid.NewGuid().ToString().Replace("-", "").Replace("0", "h").Replace("1", "k");
         
         code = newGuidString.Substring(0, 4) 
                 + "-" + newGuidString.Substring(4, 4) 
                 + "-" + newGuidString.Substring(8, 4);
        
         code = code.ToUpper().Replace("KKK", "HHH").Replace("666", "777"); // just to avoid an undesirable code

         var codeExists = (from r in DataContext.Registrations
                                  where r.Code == code
                                  select r).Any(); //test to see if the registration code already exists.  

         if (codeExists)
               code = "";
    }

    return code; 
}

Integrating Bing Search Results Within A Web App Using .NET

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

A few months ago I was faced with the challenge of including a site search in a web system we maintain.

The main goals for the search tool were meaningful results, ease of use, and low cost of implementation.

After evaluating the search offerings from Google, Bing and Yahoo we went with Bing. Microsoft offers high flexibility and no fees for using the Bing Search API. The only thing they request is that you show some type of image or statement crediting Bing with the search results.

The Bing Search API is part of Project Silk Road it offers many options for choosing the source type and output protocol (JSON, SOAP, XML) as well as flexible presentation options (No restrictions on ordering and blending of result). This allows you to integrate custom results with the Bing results without violating the usage terms.

Below are some code snippets to reference:

Retrieves the XML document containing search results from Bing and loads them into an object collection.

public BingSearchResult(string title, string description, string url)
{
     this.Title = title;
     this.Description = description;
     this.Url = url;
}

private static BingSearchResultCollection GetResults(string searchQuery, int pageNum, int resultsPerPage)
{
int offset = ((pageNum - 1) * resultsPerPage);

string url = "http://api.search.live.net/xml.aspx?Appid={0}&sources={1}&query={2}&{1}.count={3}&{1}.offset={4}";
string completeUri = String.Format(url, appID, "web", "site:www.yoursite.org " + searchQuery, resultsPerPage, offset);

HttpWebRequest webRequest = null;
HttpWebResponse webResponse = null;
XmlReader xmlReader = null;
webRequest = (HttpWebRequest)WebRequest.Create(completeUri);
webResponse = (HttpWebResponse)webRequest.GetResponse();
            
//Handles an invalid xml document
try
{
    xmlReader = XmlReader.Create(webResponse.GetResponseStream());
}
catch (System.Security.SecurityException)
{
    return new BingSearchResultCollection();
}

XDocument xmlDoc = XDocument.Load(xmlReader);
            
//Loops through the results and creates BingSearchResult objects
if (GetElementsByName(xmlDoc, "SearchResponse").Any())
{
    XElement searchResponse = GetElementsByName(xmlDoc, "SearchResponse").First();
    if(GetElementsByName(searchResponse, "Web").Any())
    {
        XElement web = GetElementsByName(searchResponse, "Web").First();
        if (GetElementsByName(web, "Total").Any())
        {
                        
            int totalResults = Convert.ToInt32(GetElementsByName(web, "Total").First().Value);
            var list = new BingSearchResultCollection(totalResults, searchQuery);

            if (GetElementsByName(web, "Results").Any())
            {
                XElement results = GetElementsByName(web, "Results").First();
                if (GetElementsByName(web, "Results").Any())
                {
                    if (GetElementsByName(results, "WebResult").Any())
                    {
                        var webResults = GetElementsByName(results, "WebResult");

                        foreach (XElement el in webResults)
                        {
                            string resTitle = "";
                            string resUrl = "";
                            string resDescr = "";
                            if (GetElementsByName(el, "Title").Any())
                                resTitle = GetElementsByName(el, "Title").First().Value;
                            if (GetElementsByName(el, "Url").Any())
                                resUrl = GetElementsByName(el, "Url").First().Value;
                            if (GetElementsByName(el, "Description").Any())
                                resDescr = GetElementsByName(el, "Description").First().Value; ;

                            if (IsValidUrl(resUrl))
                                list.Add(new BingSearchResult(resTitle, resDescr, resUrl));
                        }

                        return list;
                    }
                }
            }
        }
    }
}

return new BingSearchResultCollection();
}

private static IEnumerable<XElement> GetElementsByName(XContainer cont, String name)
{
     return (from el in cont.Elements()
          where el.Name.LocalName == name
          select el);
}

The reason I ended up using a custom LINQ function to traverse the tree was because I couldn’t figure out how to get a collection of WebResult elements.

The XML document returned from Bing is structured like this:

<?xml version="1.0" encoding="utf-8" ?> 
<?pageview_candidate ?> 
<SearchResponse xmlns="http://schemas.microsoft.com/LiveSearch/2008/04/XML/element" Version="2.2">
     <Query>
          <SearchTerms>site:www.yoursite.com SearchTerm</SearchTerms> 
     </Query>
     <web:Web xmlns:web="http://schemas.microsoft.com/LiveSearch/2008/04/XML/web">
     <web:Total>1350000</web:Total> 
     <web:Offset>0</web:Offset> 
     <web:Results>
          <web:WebResult>
               <web:Title>Result Title</web:Title> 
               <web:Description>Description of Result</web:Description> 
               <web:Url>http://www.resulturl.com</web:Url> 
               <web:CacheUrl>http://cc.bingj.com/cache.aspx?somecashobjecthere</web:CacheUrl> 
               <web:DisplayUrl>www.resulturl.com</web:DisplayUrl> 
               <web:DateTime>2010-07-02T20:27:32Z</web:DateTime> 
         </web:WebResult>
     </web:Results>
     </web:Web>
</SearchResponse>

Hopefully this gives you an idea of what you need to hit the floor running when implementing the Bing Search API in your project(s).

Here are some helpful resources:
http://www.bing.com/developers/
http://www.bing.com/developers/s/API%20Basics.pdf

If you need a powered by Bing image you can use the one I created here.