Showing posts with label postback. Show all posts
Showing posts with label postback. Show all posts

Wednesday, March 28, 2012

AJAX UpdatePanel, ASP.NET Repeater Control, and custom JavaScript for postback - Single ro

Good afternoon, everyone.

I am running into an interesting problem with the AJAX UpdatePanel and the ASP.NET Repeater control. For some background, we have been asked to develop a dynamic single row update for a data table that needs to be maintained by the users. The analyst does not want to use buttons, as this is supposed to be a data entry style of application (hands on keyboard at all times, no mouse interaction). The following rules define the behavior the analyst wants to have happen:

When a user changes the data in a row, the row should be marked as changed but not saved yet. (No individual control saves to the database.)

When a user leaves a row that has been changed, that row should be posted back to the server and saved to the database.

I was able to get this partly working with a GridView inside of an UpdatePanel, by using some custom client-side JavaScript to detect changes and to determine when to call __doPostBack to force the save to the database.

However, the entire GridView is posting back each time, which is not the desired effect. The analyst wants each row to post back individually. We are also running into enough of a performance bottleneck with the GridView postback, that we decided to try using Repeater instead, with an UpdatePanel around each row of data.

Unfortunately, changing the GridView to a Repeater turned out to be problematic. I am running into the following issues:

When the custom __doPostBack JavaScript method is called by a control inside a Repeater, which is nested inside an UpdatePanel, the entire page is posting back instead of just the UpdatePanel.

When attempting to move the JavaScript from the .aspx page to a JavaScript .js file, the client-side JavaScript aborts with an "Object expected" error when the custom __doPostBack JavaScript method is called. (The same code works fine when embedded in the .aspx page.)

I have managed to prune down the code to the bare essentials, and I was able to replicate these problems with standard ASP.NET code.

Would some of you please look over the code below and let me know if there is something obvious that I am doing wrong? Or would someone please explain why this is working fine for GridView but not for Repeater?

Thanks in advance for any help that you can provide.

We also have a suggestion to convert the custom JavaScript to server-side code by building custom controls that would expose OnFocus as a server-side event. Have any of you done something like this before? If so, do those custom controls work with the AJAX UpdatePanel?

Jeff Parker
Senior Software Developer
Explore Information Services


default.aspx - UpdatePanel contains Repeater control, client-side JavaScript embedded in the aspx page

-- default.aspx

<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> This is some text sitting outside the main control. It should not be refreshed by AJAX.<%=DateTime.Now%><br /> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" /> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional"> <ContentTemplate> <script type="text/javascript"> var currentRowChanged = -1; function SetRowChanged(rowIndex) { currentRowChanged = rowIndex; } function CheckRowChanged(repeaterUniqueID, controlID, newRowIndex) { if((currentRowChanged != -1) && (currentRowChanged != newRowIndex)) { saveInfo = 'SaveData$' + controlID + '$' + currentRowChanged + '$' + newRowIndex; currentRowChanged = -1; __doPostBack(repeaterUniqueID, saveInfo); } } </script> <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound" > <HeaderTemplate> This is inside the update panel and should be updated.<%=DateTime.Now%><br /> </HeaderTemplate> <ItemTemplate> <asp:TextBox ID="TextBox1" runat="server" />  <asp:TextBox ID="TextBox2" runat="server" />  <asp:TextBox ID="TextBox3" runat="server" /><br /> </ItemTemplate> </asp:Repeater> </ContentTemplate> </asp:UpdatePanel> </form></body></html>

-- default.aspx.cs

using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;public partialclass _Default : System.Web.UI.Page {protected void Page_Load(object sender, EventArgs e) {if(!IsPostBack) { BindData(); }else {if (Request.Form["__EVENTTARGET"].Contains(Repeater1.UniqueID.Replace(':','$'))) {if (Request.Form["__EVENTARGUMENT"].Contains("SaveData$")) {string[] aszSaveParameters = Request.Form["__EVENTARGUMENT"].Split('$');string szCurrentControlID = aszSaveParameters[1];int iSaveItemIndex = Convert.ToInt32(aszSaveParameters[2]);int iCurrentRowIndex = Convert.ToInt32(aszSaveParameters[3]); RandomizeRow(iSaveItemIndex); ScriptManager1.SetFocus(szCurrentControlID); } } } }private void RandomizeRow(int index) { RepeaterItem riSaveRow = Repeater1.Items[index]; Random oRandom =new Random(); TextBox TextBox1 = (TextBox)riSaveRow.FindControl("TextBox1"); TextBox1.Text = Convert.ToString(oRandom.Next()); TextBox TextBox2 = (TextBox)riSaveRow.FindControl("TextBox2"); TextBox2.Text = Convert.ToString(oRandom.Next()); TextBox TextBox3 = (TextBox)riSaveRow.FindControl("TextBox3"); TextBox3.Text = Convert.ToString(oRandom.Next()); }private void BindData() { Repeater1.DataSource = GetSampleData(); Repeater1.DataBind(); }private DataTable GetSampleData() { DataTable dtbSampleData =new DataTable(); dtbSampleData.Columns.Add("TestColumn1",typeof(string)); dtbSampleData.Columns.Add("TestColumn2",typeof(string)); dtbSampleData.Columns.Add("TestColumn3",typeof(string)); DataRow drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 1"; drSampleData["TestColumn2"] ="column 2, row 1"; drSampleData["TestColumn3"] ="column 3, row 1"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 2"; drSampleData["TestColumn2"] ="column 2, row 2"; drSampleData["TestColumn3"] ="column 3, row 2"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 3"; drSampleData["TestColumn2"] ="column 2, row 3"; drSampleData["TestColumn3"] ="column 3, row 3"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 4"; drSampleData["TestColumn2"] ="column 2, row 4"; drSampleData["TestColumn3"] ="column 3, row 4"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 5"; drSampleData["TestColumn2"] ="column 2, row 5"; drSampleData["TestColumn3"] ="column 3, row 5"; dtbSampleData.Rows.Add(drSampleData); dtbSampleData.AcceptChanges();return dtbSampleData; }protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e) {if((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem)) { DataRowView drvSampleData = (DataRowView) e.Item.DataItem; TextBox TextBox1 = (TextBox)e.Item.FindControl("TextBox1"); TextBox1.Text = Convert.ToString(drvSampleData["TestColumn1"]); TextBox1.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox1.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; TextBox TextBox2 = (TextBox)e.Item.FindControl("TextBox2"); TextBox2.Text = Convert.ToString(drvSampleData["TestColumn2"]); TextBox2.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox2.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; TextBox TextBox3 = (TextBox)e.Item.FindControl("TextBox3"); TextBox3.Text = Convert.ToString(drvSampleData["TestColumn3"]); TextBox3.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox3.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; } }protected override void RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl,string eventArgument) {if ((eventArgument !=null) && (eventArgument.Contains("SaveData$"))) {// Do nothing }else {base.RaisePostBackEvent(sourceControl, eventArgument); } }}

default2.aspx - UpdatePanel contains Repeater control, client-side JavaScript included using ScriptManager.RegisterClientScriptInclude method

-- default2.aspx

<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="_Default2" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title>Untitled Page</title></head><body> This is some text sitting outside the main control. It should not be refreshed by AJAX.<%=DateTime.Now%><br /> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" /> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional"> <ContentTemplate> <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound" > <HeaderTemplate> This is inside the update panel and should be updated.<%=DateTime.Now%><br /> </HeaderTemplate> <ItemTemplate> <asp:TextBox ID="TextBox1" runat="server" />  <asp:TextBox ID="TextBox2" runat="server" />  <asp:TextBox ID="TextBox3" runat="server" /><br /> </ItemTemplate> </asp:Repeater> </ContentTemplate> </asp:UpdatePanel> </form></body></html>

-- default2.aspx.cs

using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;public partialclass _Default2 : System.Web.UI.Page {protected void Page_Load(object sender, EventArgs e) {if(!IsPostBack) {if (!ClientScript.IsClientScriptIncludeRegistered("SingleRowUpdate")) { ScriptManager.RegisterClientScriptInclude(this,typeof (Page),"SingleRowUpdate","JScript.js"); } BindData(); }else {if (Request.Form["__EVENTTARGET"].Contains(Repeater1.UniqueID.Replace(':','$'))) {if (Request.Form["__EVENTARGUMENT"].Contains("SaveData$")) {string[] aszSaveParameters = Request.Form["__EVENTARGUMENT"].Split('$');string szCurrentControlID = aszSaveParameters[1];int iSaveItemIndex = Convert.ToInt32(aszSaveParameters[2]);int iCurrentRowIndex = Convert.ToInt32(aszSaveParameters[3]); RandomizeRow(iSaveItemIndex); ScriptManager1.SetFocus(szCurrentControlID); } } } }private void RandomizeRow(int index) { RepeaterItem riSaveRow = Repeater1.Items[index]; Random oRandom =new Random(); TextBox TextBox1 = (TextBox)riSaveRow.FindControl("TextBox1"); TextBox1.Text = Convert.ToString(oRandom.Next()); TextBox TextBox2 = (TextBox)riSaveRow.FindControl("TextBox2"); TextBox2.Text = Convert.ToString(oRandom.Next()); TextBox TextBox3 = (TextBox)riSaveRow.FindControl("TextBox3"); TextBox3.Text = Convert.ToString(oRandom.Next()); }private void BindData() { Repeater1.DataSource = GetSampleData(); Repeater1.DataBind(); }private DataTable GetSampleData() { DataTable dtbSampleData =new DataTable(); dtbSampleData.Columns.Add("TestColumn1",typeof(string)); dtbSampleData.Columns.Add("TestColumn2",typeof(string)); dtbSampleData.Columns.Add("TestColumn3",typeof(string)); DataRow drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 1"; drSampleData["TestColumn2"] ="column 2, row 1"; drSampleData["TestColumn3"] ="column 3, row 1"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 2"; drSampleData["TestColumn2"] ="column 2, row 2"; drSampleData["TestColumn3"] ="column 3, row 2"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 3"; drSampleData["TestColumn2"] ="column 2, row 3"; drSampleData["TestColumn3"] ="column 3, row 3"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 4"; drSampleData["TestColumn2"] ="column 2, row 4"; drSampleData["TestColumn3"] ="column 3, row 4"; dtbSampleData.Rows.Add(drSampleData); drSampleData = dtbSampleData.NewRow(); drSampleData["TestColumn1"] ="column 1, row 5"; drSampleData["TestColumn2"] ="column 2, row 5"; drSampleData["TestColumn3"] ="column 3, row 5"; dtbSampleData.Rows.Add(drSampleData); dtbSampleData.AcceptChanges();return dtbSampleData; }protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e) {if((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem)) { DataRowView drvSampleData = (DataRowView) e.Item.DataItem; TextBox TextBox1 = (TextBox)e.Item.FindControl("TextBox1"); TextBox1.Text = Convert.ToString(drvSampleData["TestColumn1"]); TextBox1.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox1.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; TextBox TextBox2 = (TextBox)e.Item.FindControl("TextBox2"); TextBox2.Text = Convert.ToString(drvSampleData["TestColumn2"]); TextBox2.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox2.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; TextBox TextBox3 = (TextBox)e.Item.FindControl("TextBox3"); TextBox3.Text = Convert.ToString(drvSampleData["TestColumn3"]); TextBox3.Attributes["onchange"] ="javascript:SetRowChanged(" + e.Item.ItemIndex +")"; TextBox3.Attributes["onfocus"] ="javascript:CheckRowChanged('" + Repeater1.UniqueID +"', '" + TextBox1.ClientID +"', " + e.Item.ItemIndex +")"; } }protected override void RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl,string eventArgument) {if ((eventArgument !=null) && (eventArgument.Contains("SaveData$"))) {// Do nothing }else {base.RaisePostBackEvent(sourceControl, eventArgument); } }}

-- JScript.js

// JScript Filevar currentRowChanged = -1;function SetRowChanged(rowIndex){ currentRowChanged = rowIndex;}function CheckRowChanged(repeaterUniqueID, controlID, newRowIndex){if((currentRowChanged != -1) && (currentRowChanged != newRowIndex)) { saveInfo ='SaveData$' + controlID +'$' + currentRowChanged +'$' + newRowIndex; currentRowChanged = -1; __doPostBack(repeaterUniqueID, saveInfo); } }

web.config - project web config file

<configuration><configSections><sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"><sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"><section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/><sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"><section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/><section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/><section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/></sectionGroup></sectionGroup></sectionGroup></configSections><system.web><pages><controls><add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></controls></pages><!-- Set compilation debug="true" to insert debugging symbols into the compiled page. Because this affects performance, set this value to true only during development. --><compilation debug="true"><assemblies><add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></assemblies></compilation><httpHandlers><remove verb="*" path="*.asmx"/><add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/></httpHandlers><httpModules><add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></httpModules></system.web><system.web.extensions><scripting><webServices><!-- Uncomment this line to customize maxJsonLength and add a custom converter --><!-- <jsonSerialization maxJsonLength="500"> <converters> <add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/> </converters> </jsonSerialization> --><!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. --><!-- <authenticationService enabled="true" requireSSL = "true|false"/> --><!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and writeAccessProperties attributes. --><!-- <profileService enabled="true" readAccessProperties="propertyname1,propertyname2" writeAccessProperties="propertyname1,propertyname2" /> --></webServices><!-- <scriptResourceHandler enableCompression="true" enableCaching="true" /> --></scripting></system.web.extensions><system.webServer><validation validateIntegratedModeConfiguration="false"/><modules><add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></modules><handlers><remove name="WebServiceHandlerFactory-Integrated"/><add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/><add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></handlers></system.webServer></configuration>
Ok, here is a little secret about Update panel!Update panel posts back everything as in traditional .NET 1.1 Post back.Only at the rendering on the server does it realizes that it would only need to send what is in the update panel and sends only that part as response.So, your request is same as the post-back model. Only your response is minimized.I guess what you should be doing is making a call to Web Service or Web Method in a page and use JSON for serialization.

This way you would only send what you need to send and get back what is necessary...but you would have to write some Java Script :)


I can understand what you are saying to a certain degree. Indeed that is something to look into (and something to argue about with developers that don't like JavaScript) for performance increases. Thanks, Ravivb, for the info. I was not aware of JSON.

Unfortunately, there is still the root problem I'm having with AJAX. Somehow the server is not recognizing that it needs to refresh only a certain portion of the page. It is re-rendering everything. In the sample provided, the time outside the UpdatePanel is updated along with the time inside the UpdatePanel on every row change. Thus AJAX does not appear to be working at all on this page, as everything is posting back and being refreshed, rather than just the section inside the UpdatePanel.

Also, I don't understand why the JavaScript can't be loaded from a JavaScript .js file. It shouldn't make any difference if the JavaScript is embedded in the page or if it is being included from a file. But for some reason there is a difference.

Jeff


I have not followed your entire code to give proper answer on JavaScript problem.

But, if i were you, i would start at looking in to java script file path mapping to see if the path mapping is done right once the html is sent to client..

Next, try to debug java script to see what is going on. (you could use Firebug for FF or IE developer Toolbar fromhere

-good luck


Kalnir,

try looking into webservice. I have a few pages that are huge, doing postback on them is a pain in the b**t. Your webservice can be called from your javascript function.


Thanks, Ravivb and WishStar99. I just read up on JSON and the ASP.NET callback event technique, and I'm starting to work on constructing a test version of the page using the technique. I'll keep the webservice call in mind as well.

I'm not sure that will fix the problem I'm having with Repeater inside UpdatePanel, though. Any idea why the whole page is flashing instead of just the UpdatePanel region?


Heya, folks.

I want to thank Ravivb and WishStar99 for their help with this problem. The application was modified to use JSON and the ASP.NET callback event technique. The solution appears to be working fine and is fast enough to be acceptable to the end users.

The following articles helped me learn about JSON and how to work with it in .NET:

JSON (JavaScript Object Notation) data interchange format: http://json.org/


Glad it worked out...


Hi Jeff,

Can you show me in which article I can see some code sample for refreshing the gridView single row, as u did instead of using updatepanels.

I can t find some code sample where I refer the gridview or datagrid's single row.

Anyway, can u show us some code sample pls for doing what u did. i didn t find that on internet. I m not talking about calling the webmethod but especially m talking about the javascript DOM part that takes the result send by the webmethod and refreshes the datagrid or gridview's single row.

Thanks a lot.


Very interesting info on the JSON stuff.

I wanted to mention that I have almost successfully implemented a fully Ajax website using asp.net 2.0, however with one major problem. I have a Repeater object inside the UpdatePanel control, but everytime the Timer control kicks fires the asynch update it freezes up all of the page controls (i.e. hyperlinks, dropdownlists, etc.).

I have an update image that flashes with every Asynch update; and everytime the image appears I cannot click on any links nor access the dropdown lists. It's very frustrating.

Has anyone experiences this with a Repeater inside an UpdatePanel ? Any advice or ideas ?

Thank you very much,

Bob

Monday, March 26, 2012

AJAX to do Server Side Validation without entire page postback

Hi,

I'm relatively new to ajax, but have an idea i'd like to try.

Is there any way to call a server side method that is able to access the values of items on a form, i.e post a form for validation, but without doing an entire page postback, and return a string with the validation results?

I'm having trouble figuring out how post a form without doing a postback.

Thanks in advance.

Chris

Hi,

The short answer is no. There's no way to "post" a form for validation without doing a partial postback which still causes the server lifecycle to be executed.


The solution that you're looking for is to execute a web service (or page method if you so chose) from client code that takes as parameters the current values of the form fields you're attempting to validate. You would execute the web service from client side JavaScript and grab the current values of your needed form fields also using JavaScript.

Look at the docs that describe executing a web service from client code.


Ajax Timer without postback

I have place an Ajax timer to databind a datalist inside an update panel. The anoying thing is that it keep doing postback everytime. I thought that having the datalist and the timer inside the update panel wouldnt cause an postback. Is there anyway to do a databind without a postback?

Thanks,

Erick

Can you provide your code for your Timer.Tick event?

Protected Sub Timer1_Tick(ByVal senderAs Object,ByVal eAs System.EventArgs)Handles Timer1.Tick MsgList.DataBind()End Sub
Nothing fancy just the databind, still it creates a postback been inside the updatepanel

When you say it creates a postback, do you mean a full postback or a partial one? A Timer and UpdatePanelare intended to generate partial postbacks each tick, which often isn't very desirable.


gt1329a:

When you say it creates a postback, do you mean a full postback or a partial one? A Timer and UpdatePanelare intended to generate partial postbacks each tick, which often isn't very desirable.

It's a partial postback, but I have a textbox in the page outside of the update panel and if you are writing at the moment of the postback it would cut what you are writing and lose focus.

Any other way to do a databind without causing a postback?


A partial postback alone shouldn't affect focus of anything that's outside of an UpdatePanel.

Is there anything like a SetFocus() in the code that runs in the Tick event (or Page_Load, etc if they aren't wrapped in a !IsPostBack) that might be stealing focus from the TextBox when the partial postback completes?

Is the TextBox in another UpdatePanel itself, with UpdateMode not set to Conditional?


Private Sub Page_Load(ByVal senderAs System.Object,ByVal eAs System.EventArgs)Handles MyBase.Load,Me.LoadTry If Not Page.IsPostBackThen If UserInfo.DisplayName =""Then txtMsg.Enabled =False btnSend.Enabled =False Else Dim SQLActivateUserAs String ="UPDATE RoomUser SET is_active = 1 WHERE user_id = 6"Dim SQLConAs New SqlConnection(ConfigurationManager.ConnectionStrings("SiteSqlServer").ConnectionString)Dim SQLCmdAs New SqlCommand(SQLActivateUser, SQLCon) SQLCon.Open() SQLCmd.ExecuteNonQuery() SQLCon.Close()End If End If Catch excAs Exception ProcessModuleLoadException(Me, exc)End Try End Sub Protected Sub btnSend_Click(ByVal senderAs Object,ByVal eAs System.EventArgs)Handles btnSend.ClickDim Username, Message, SQLInsertMsgAs String Username = UserInfo.DisplayName Message = txtMsg.Text SQLInsertMsg ="INSERT INTO Message (room_id,msg_ts,ip_addr,msg_from_userid,msg_to_userid,msg_color,msg_text,msg_type) VALUES (1,'" + Date.Now + "','192.168.1.1',6,-1,'#000000','" + Message + "',0)" Dim SQLCon As New SqlConnection(ConfigurationManager.ConnectionStrings("SiteSqlServer").ConnectionString) Dim SQLCmd As New SqlCommand(SQLInsertMsg, SQLCon) SQLCon.Open() SQLCmd.ExecuteNonQuery() SQLCon.Close() txtMsg.Text = "" MsgList.DataBind()End Sub Protected Sub Timer1_Tick(ByVal senderAs Object,ByVal eAs System.EventArgs)Handles Timer1.Tick MsgList.DataBind()End Sub End Class
This is my code, there is no use of setfocus()

Can you show your ASPX HTML code?


I test it and I think it can work well. The difference between your code and mine is that I use sitemap istead of using SQL server operation. My code is as following:

.cs code :

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
private static int mNumber = 0;
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Timer1_Tick1(object sender, EventArgs e)
{
if ((mNumber % 2) == 0)
{
msgList.DataSourceID = "TestDataSiteMap";
}
else
{
msgList.DataSourceID = "TestDataSiteMap2";
}

msgList.DataBind();
mNumber++;
}
protected void Button1_Click(object sender, EventArgs e)
{
TextBox2.Text = TextBox1.Text;
}
}

.aspx code:

<%@. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@. Import Namespace="System"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form ID="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:TextBox ID="TextBox1" runat="server" Width="342px"></asp:TextBox><br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /><br />
<asp:TextBox ID="TextBox2" runat="server" Width="339px"></asp:TextBox><br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Interval="6000" OnTick="Timer1_Tick1"></asp:Timer>
<asp:SiteMapDataSource ID="TestDataSiteMap" SiteMapProvider="TestDataSiteMap" runat="server" ShowStartingNode="false"/>
<asp:SiteMapDataSource ID="TestDataSiteMap2" SiteMapProvider="TestDataSiteMap2" runat="server" ShowStartingNode="false"/>
<asp:Panel ID="Panel1" runat="server" Height="62px" Width="207px">
<asp:ListBox ID="msgList" runat="server" Height="118px" Width="202px" DataSourceID="TestDataSiteMap"></asp:ListBox>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
<br />
</body>
</html>


And I also found there will be no effect when I am typing on a textbox outside the UpdatePanel.

Wednesday, March 21, 2012

AJAX tab control postback of dropdown event in VB

I've read so many posts my head is spinning! So, I'm struggling w/ the autopost back of a dropdown from within a AJAX tab control.
Does anyone have a simple example? Here's my code.

<asp:ScriptManagerID="ScriptManager1"runat="server">
</asp:ScriptManager>
<asp:SqlDataSourceID="SqlEvents"runat="server"ConnectionString="<%$ ConnectionStrings:LLB_Con %>"
SelectCommand="SELECT [T], [X] FROM [Events] ORDER BY [startdate] desc"></asp:SqlDataSource>
<ajaxToolkit:TabContainerID="tabAdmin"runat="server"ActiveTabIndex="1"Height="512px"Width="1121px">
<ajaxToolkit:TabPanelID="TabPanel1"runat="server"HeaderText="Manage Data">
<ContentTemplate><br/>
<asp:HyperLinkID="hlEventFormat"runat="server"NavigateUrl="~/Admin/Event_Format.aspx"Text="Manage Event Format"/>
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanelID="tpProcessing"runat="server"HeaderText="Event Processing">
<ContentTemplate><br/> <br/><br/>
<asp:DropDownListID="ddEvents"runat="server"
DataSourceID="SqlEvents"
DataTextField="T"
DataValueField="X"/><asp:HyperLinkID="hlEnter_Event"runat="server"Text="Enter Event Data"NavigateUrl="~/Admin/eventEntry.aspx"/>
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>

I think you need to add at the DropDownList

AutoPostBack="True"

George