Question

VS2010 page with an UpdatePanel and a UserControl. The page is a search utility for a large table with > 10 criteria. The UpdatePanel receives the search results. The UserControl is a new addition to the page.

Let's say the page finds people who own music CDs. Previously, each person had a genre associated with their ID and this was a 1-1 relationship. The DB has been updated to support Many-to-many so the UserControl is there to implement the selection of multiple genres when searching.

Basically, whereas before you could only find people into Heavy Metal. You can now find people into Heavy Metal AND Punk (AND ...)

The usercontrol sends an html table back to the page and jQuery responds to keyup() by changing the CSS classes so that the possible options are either invisible, visible or pinned if the user clicks on a visible one.

So I have this:

<tr class='genre_hidden'><td>Jazz-Bebop</td></tr>
<tr class='genre_hidden'><td>Jazz-Trad</td></tr>
<tr class='genre_hidden'><td>Jazz-Dixie</td></tr>
<tr class='genre_pinned'><td>Punk</td></tr>
<tr class='genre_pinned'><td>Heavy Metal</td></tr>
<tr class='genre_visible'><td>Classic Rock</td></tr>

The handler for the trigger calls a sproc, which I've changed to accept a table value parameter of the selected genres. What I need is a way of getting those genres from $('.genre_pinned') to the handler so I can build the DataTable to pass to the sproc.

Cheers, .pd.

What I have working:

- handle click event of Search button in UpdatePanel
    -- in this function, fire an ajax request to a webmethod on the main page
    -- webmethod generates key for session and 
    -- ajax success copies key to a server hidden input
    -- preventdefault not called so normal button action occurs
- button click handler on server side
    -- retrieve key from hidden control
    -- convert list to datatable fitting table value parameter type
    -- add datatable to params and call sproc

Am I breaking any rules/is there a better way?

Was it helpful?

Solution

Okay, well looks like I'll have to answer my own question then. Here are the snippets people will need if you wanna do it the same way I did.

Hope it helps somebody,

Cheers, .pd.

In the page you've put the user control on, you need to catch the click that submits the updatepanel.

<script type="text/javascript">
    $(subscribeClicks);

    // for use on pages with updatepanels.  once the panel has reloaded, the jquery
    // events get slagged so we need to rebind them here.
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_endRequest(subscribeClicks);

    function subscribeClicks() {
        // catch the search button before it (partially) posts back and send
        // data 
        $('input[id*="btnSearch"]').click(function (e) {
           // this function is in a script in your usercontrol
           senddataFromUserControl('ThisPage.aspx/NameOfYourWebMethod');
        });
    }
</script>

In your usercontrol you need senddataFromUserControl to ajax your form data to the codebehind. Note the success part where the hidden element receives the Session key. And also the async : false (thanks Kevin B).

function senddataFromUserControl(url) {
    var arr = new Array();
    var ele = $('.jq_idt_selected');
    for (var i = 0; i < ele.length; i++) {
        arr.push({ Name: $(ele[i]).find('.jq_idt_path').text(), Value: $(ele[i]).find(':hidden').val() });
    }

    $.ajax({
        type: "POST",
        async: false,
        url: url,
        data: "{args:" + JSON.stringify(arr) + "}",
        dataType: "text",
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            $('input[id*="hdnSessionKey"]').val($.parseJSON(data)["d"]);
        },
        error: function (data) {
            alert(data.responseText);
        }
    });
}

In your code behind, set up the class to receive name/value pairs (this one's in VB)

Public Class SearchArgs
    Public Name As String
    Public Value As String
End Class

And in C#:

public class SearchArgs {
    public string Name;
    public string Value;
}

Then code your webmethod (VB first)

<System.Web.Services.WebMethod()> _
Public Shared Function NameOfYourWebMethod(args As List(Of SearchArgs)) As String
    ' generate a session key for the client to pass back when the page postback occurs
    Dim key As String = String.Format("IDT_{0:yyMMddhhmmss}", Now)
    HttpContext.Current.Session(key) = args
    Return key
End Function

Here's a C# version:

[System.Web.Services.WebMethod()]
public static string NameOfYourWebMethod(List<SearchArgs> args)
{
    // generate a session key for the client to pass back when the page postback occurs
    string key = string.Format("IDT_{0:yyMMddhhmmss}", DateAndTime.Now);
    HttpContext.Current.Session[key] = args;
    return key;
}

Finally in the submit button click, grab the extra data from Session.

    Dim o As Object = yourUserControl.FindControl("hdnSessionKey")
    Dim hdn As HtmlInputHidden = CType(o, HtmlInputHidden)
    If hdn IsNot Nothing Then
        Dim key As String = hdn.Value
        Dim filterValues As List(Of SearchArgs) = CType(Session(key), List(Of SearchArgs))
        For Each filterValue As SearchArgs In filterValues
            ' do what you need to prep this for your data layer
        Next
        Session(key) = Nothing
    End If

And in C#:

object o = yourUserControl.FindControl("hdnSessionKey");
HtmlInputHidden hdn = (HtmlInputHidden)o;
if (hdn != null) {
    string key = hdn.Value;
    List<SearchArgs> filterValues = List<SearchArgs>)Session[key];
    foreach (SearchArgs filterValue in filterValues) {
        // do what you need to prep this for your data layer
    }
    Session[key] = null;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top