views:

981

answers:

1

Hello,

Today i faced a pretty weird problem, made of a stored procedure, an autocompleteextender and event handling. If anyone can suggest a concise title for the following saga, please do!

First i'll try to introduce the players (some parts are a bit abridged) and then the scenarios. Environment is VS2008, C#, SQL Server 2005 and ASP.NET.

DB table:

TABLE (
 SomeNbr  INT,
 SomeAbbr VARCHAR(10),
 Name     VARCHAR(30)
)

StoredProcedure:

Reads the table above and returns something like this:

DECLARE @Results TABLE
(
    SomeNbr INT,
    --Composite CHAR(50), -- voodoo magic starts here...
    Composite VARCHAR(50)
)

Composite-field of the return table is made of SomeNbr, SomeAbbr and Name fields. They are appended together and separated by commas (f.ex. "number, abbreviation, name").

Stored Procedure is used to retrieve a set of rows from db, and these are put into a typed datatable. This datatable is then stored in a session variable. DataTable's XSD-Schema has datatype String for the "Composite"-field.

!Important! For some rows in the db, "Name"-field contains the actual value and rpadding (made of spaces) up to the maximum length. Other just contain the name with no rpadding.

User interface (ASPX-page with codebehind):

I have extended textbox-control to include an AutoCompleteExtender from AJAX Control Toolkit. Control is declared as follows:

<ajx:TextControl ID="txtControl" 
                 runat="server" 
                 AutoPostBack="true" 
                 UseAutoComplete="true" 
                 ServiceMethod="GetItems" 
                 MinimumPrefixLength="1" />

There are some additional basic textboxes on the ui.

CodeBehind:

AutoCompleteExtender uses the following webmethod:

[System.Web.Services.WebMethod]
public static string[] GetItems(string prefixText, int count)
{
    try
    {
        return Utility.GetMatchingStrings(_DataTableInSession, prefixText);
    }        
    catch (Exception ex)
    {
        throw;
    }
}

GetMatchingStrings(...)-method compares preFixText against all datarows in _DataTableInSession, and returns an array of matching strings. Comparison is done with the datarows' "Composite"-fields.

In codebehind, the event handler gets set:

extendedTextControl.Control.TextChanged += PopulateTextControls;

, and:

private void PopulateTextControls(object sender, EventArgs e)
{
    // Read Text-property from extended textcontrol
    string str = extendedTextControl.Text;

    // Split string by commas and take parts into an array
    string[] arrStr = SplitString(",", str);

    // Set the values in array to Text-properties of TextBoxes
    SetValuesToTextBoxes(arrStr, _TextBoxes);
}

Scenarios

Everything seems to be fine, the extended TextControl is working as it is supposed to and generates the selectable list below the textbox.

Scenario 1:

Now, when user selects an item from autocompletion list the following things happen:

  1. Selected string is set to Text-property of the extended textcontrol
  2. textcontrol's autopostback happens
  3. on postback, an eventhandler is registered for textcontrol's TextChanged-event
  4. TextChanged-event is fired and other textboxes get filled with data as expected

For this scenario to happen, the "Composite"-field in the typed datarow has to be something like this:

"10", "10, ABBR, Some Name Goes Here____..._" (<- spaces replaced with underscores)

If the datarow is more like this:

"10", "10, ABBR, Some Name Goes Here"

then we'll go to...

Scenario 2:

The above is a sort of happy day -scenario :-)

If the matching datarow is made from a row in db where "Name"-field is not padded with spaces up to the maximum length (VARCHAR(50)), then the TextChanged-event does not get fired.

I spent a good few hours trying to figure out everything above. First i was quite confused that why the **** selecting some of the items in autocompletion list do work, and some don't.

When i realized to look at the datatable's contents, i saw that some rows had the padding and others did not. After that i tried to ltrim(rtrim()) everything in the SP's return table, and none of the items worked anymore.

After that i tried to set the SP's return value to CHAR(50) instead of VARCHAR(50), and that fixed it.

Question:

What is going on in my application? Why doesn't the registered event fire? It's like TextChanged would only work for string of certain length (max length of the VARCHAR(50)), but how would that be possible?

Problem is solved, but i have no idea why. Just another day at the office, i suppose :-)

I'll be happy to provide additional data and clarifications!

Edit 1: Added note about spaces and underscores within the datarow.

A: 

After that i tried to set the SP's return value to CHAR(50) instead of VARCHAR(50), and that fixed it.

I didn't understand the whole scenario but I would look at the CHAR(50) vs. VARCHAR(50) issue. I also do not know what "WebOlkiUtility.GetMatchingStrings" does.

declare @text char(50)
select @text = 'test'

select @text

declare @text2 varchar(50)
select @text2 = 'test2'

select @text2

-- output --
CHAR(50): 'test                                              '
VARCHAR(59): 'test2'

CHAR(50) returns always 50 Character!

BTW: Why do you attach the event this way?

if (GetPostBackingControlId() == extendedTextControl.ID)
{
    extendedTextControl.Control.TextChanged += PopulateTextControls;
}

You could attach it always. In your ASPX file or in the Page_Init Method.

Arthur
Utility-method is used for getting the matching items from the DataTable. Method returns the items that matched user input as an array of strings, as required by the AutoCompleteExtender. Event handler code looks a bit weird, but that's because of me abridging the code. I'll edit the example a bit.
juarola