Monday, March 7, 2005

Passing client data to the server

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/passing_client_data_to_the_server.htm]

In my last post, I discussed how to set hidden fields in UserControls to ensure that the control is reusable. This post will expand on that, showing how to use hidden fields as a bridge to pass data between the client and server.

There are several cases where you'd want to have a client-side GUI control, let the user trigger it, do some client side activity first (validation, prompt, etc...), and then send the appropriate data from that control back to the server. For example:

  • MessageBox - Get the value of the clicked button.
  • Image Map - Get the value of the selected region.
  • Dynamically generated links - Get the specific link that was selected.

The basic approach to do this is:

  1. Create a hidden field, runat=server, viewstate enabled (this is default) to store the client side value.
  2. In the CodeBehind of the UserControl, wrap that hidden field in a public property This is especially useful if there's any transformation on it, such as a default value if empty, or encoding/decoding. It also easily lets external objects, such as the hosting page or nested control, get the data because the hidden field should be protected.
  3. Have your client-side object call a JavaScript function, passing in the UserControl ClientId.
  4. In that function, (1) set the hidden field to the value you need, and (2) submit the form.

For example, I created a UserControl with a client-side image map that returns the selected region to the server.

I first added the hidden field "HdnRegionId" (runat=server).

In the code-behind, I added the property:

public string RegionId
{
    get
    {
        return this.HdnRegionId.Value;
    }
}

Still in the code-behind, I also created a public instance variable strClientId to store the User Control's Client Id. This is set every time in the UC page load:

public string strClientId;

private void Page_Load(object sender, System.EventArgs e)
{
    strClientId = this.ClientID;
}

Moving to the Aspx page, I created this JavaScript method in the Html:

function GetRegion(strKey, strClientId) {
    eval('document.forms[0].' + strClientId + '_HdnRegionId').value = strKey;
    document.forms[0].submit();
}

However, I still need a client-side object to call the javascript method:


   
   

For review, here's the flow:

  1. Server:
    1. Page_Load instantiates strClientId variable to hold the UserControl's ClientID.
  2. Client:
    1. Aspx page is rendered, all the <%= strClientId %>"> store the actual UserControl id.
    2. User does some client action, like clicking an image on the image map. This triggers the JavaScript method GetRegion, passing in both the value and ClientId.
    3. Given the UserControl client Id, the JavaScript method dynamically assembles the code needed to set the hidden field on that UserControl. It then submits the form, returning flow to the server.
  3. Server:
    1. Optional logic can be done in the Page_Load.
    2. The hidden field value is persisted in viewstate and is now accessible to other controls.

No comments:

Post a Comment