This affects lots of ajax functionality, but for this example, I'll use the ajax spell checker in the radeditor. I had some users complain that the spell checker seemed to 'freak out' every now and then, and I traced it to this.
To reproduce, use forms authentication with a login URL and a short timeout of 1, (just so you don't have to wait long for this test).
| <authentication mode="Forms"> |
| <forms name=".userauth" loginUrl="IC/Login.aspx" protection="All" timeout="1"/> |
| </authentication> |
Wait at least a minute then click on spell check. You should get this JavaScript error:
Microsoft JScript runtime error: Sys.ArgumentException: Cannot deserialize. The data does not correspond to valid JSON.
Parameter name: data
This happens because the forms auth. timed out and the ajax request was redirected to the login page. The login page is HTML and not JSON, so MS ajax throws the above error. The spell checker is left onscreen and cannot be closed as both Finish and Cancel are disabled.
My question is: is there anything that can be done for this, like catching the error somehow, and throwing up a login dialog?
What I have done in the past is ping the server every 10 minutes with JavaScript to keep formsauth. alive. I'd like to avoid that technique if possible as it didn't seem to be reliable all the time, and it left users logged in too long.
Thanks

| <head runat="server"> |
| <title></title> |
| <link href="Style/styles.css" rel="Stylesheet" type="text/css" /> |
| <link rel="SHORTCUT ICON" href="Style/Images/logo-class-I_browser.ico" /> |
| <telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server" /> |
| <style type="text/css"> |
| .rcbHeader ul, .rcbFooter ul, .rcbItem ul, .rcbHovered ul, .rcbDisabled ul |
| { |
| width: 100%; |
| display: inline-block; |
| margin: 0; |
| padding: 0; |
| list-style-type: none; |
| } |
| .col1, .col2, .col3 |
| { |
| float: left; |
| width: 100px; |
| margin: 0; |
| padding: 0 5px 0 0; |
| line-height: 14px; |
| } |
| </style> |
| </head> |
| <body> |
| <form id="form1" runat="server"> |
| <telerik:RadScriptManager ID="RadScriptManager1" runat="server"> |
| <Scripts> |
| <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" /> |
| <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" /> |
| <asp:ScriptReference Path="~/UserClassi.js" /> |
| </Scripts> |
| </telerik:RadScriptManager> |
| <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"> |
| </telerik:RadAjaxManager> |
| <telerik:RadFormDecorator ID="RadFormDecorator1" runat="server" DecoratedControls="Default,Zone" /> |
| <div> |
| <helpDesk:SkinManager runat="server" ID="RadSkinManager1" ShowChooser="false" Skin="Vista" |
| PersistenceKey="SkinDef" PersistenceMode="Session" OnPreRender="RadSkinManager1_PreRender" /> |
| </div> |
| <telerik:RadSplitter ID="RadSplitter2" runat="server" Width="100%" BorderSize="0" |
| BorderStyle="None" PanesBorderSize="0" Height="100%" Orientation="Horizontal" |
| VisibleDuringInit="false"> |
| <telerik:RadPane ID="topPane" runat="server" Height="74px" CssClass="toppane"> |
| <div class="header"> |
| <asp:Panel ID="Panel1" runat="server"> |
| <asp:Image ID="ImageLogo" runat="server" ImageUrl="Logo/logo-classi.png" ImageAlign="Middle" /> |
| </asp:Panel> |
| <div class="skin-chooser"> |
| <asp:LoginView ID="LoginView1" runat="server"> |
| <AnonymousTemplate> |
| Not authentificated</AnonymousTemplate> |
| <LoggedInTemplate> |
| <asp:LoginName ID="LoginName1" runat="server" ForeColor="Black" /> |
| <asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="RedirectToLoginPage" |
| OnLoggedOut="LoginStatus1_LoggedOut" ToolTip="Déconnexion" /> |
| <asp:LinkButton runat="server" Visible="false" ID="LinkAdmin" CausesValidation="False"> |
| <asp:ImageButton ID="ImgAdmin" runat="server" Visible="false" ImageAlign="Middle" |
| ImageUrl="~/Images/icone_administration.png" CausesValidation="False" /></asp:LinkButton> |
| </LoggedInTemplate> |
| </asp:LoginView> |
| </div> |
| </div> |
| <telerik:RadMenu ID="RadMenu1" runat="server" Style="float: none; position: absolute; |
| top: 48px; z-index: 3000" Width="100%" |
| CausesValidation="False"> |
| <Items> |
| <telerik:RadMenuItem Text="Application"> |
| <Items> |
| <telerik:RadMenuItem Text="Déconnexion" Value="logout" ImageUrl="Images/exit.gif" |
| PostBack="true" runat="server" NavigateUrl="logout.aspx" /> |
| <telerik:RadMenuItem Text="Page Principale" Value="home" ImageUrl="Images/Home.png" |
| PostBack="false" runat="server" NavigateUrl="Home2.aspx" /> |
| </Items> |
| </telerik:RadMenuItem> |
| </Items> |
| </telerik:RadMenu> |
| </telerik:RadPane> |
| <telerik:RadPane runat="server" ID="contentPane" Scrolling="none" Locked="True"> |
| <telerik:RadSplitter ID="RadSplitter1" runat="server" Height="100%" Width="100%"> |
| <telerik:RadPane ID="RadPane1" runat="server" Height="100%" Width="200px" |
| MaxWidth="300" Locked="True"> |
| <telerik:RadPanelBar ID="RadPanelBar1" runat="server" |
| ExpandMode="FullExpandedItem" Height="100%" PersistStateInCookie="True" |
| Width="100%" onitemclick="RadPanelBar1_ItemClick"> |
| <Items> |
| <telerik:RadPanelItem runat="server" Expanded="True" Selected="True" |
| Text="Groupes" Value="grp" Width="100%" PostBack="false"> |
| <Items> |
| <telerik:RadPanelItem runat="server" Text="Liste des groupes"> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Ajouter un groupe"> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Éditer un groupe"> |
| </telerik:RadPanelItem> |
| </Items> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Utilisateurs" PostBack="false"> |
| <Items> |
| <telerik:RadPanelItem runat="server" Text="Liste des utilisateurs" Value="userlist"> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Ajout d'un utilisateur"> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Édition d'un utilisateur" Value="edituser"> |
| </telerik:RadPanelItem> |
| </Items> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Licence"> |
| </telerik:RadPanelItem> |
| <telerik:RadPanelItem runat="server" Text="Statistique"> |
| </telerik:RadPanelItem> |
| </Items> |
| </telerik:RadPanelBar> |
| </telerik:RadPane> |
| <telerik:RadSplitBar ID="RadSplitBar1" runat="server" CollapseMode="None" |
| EnableResize="False" /> |
| <telerik:RadPane ID="RadPane2" runat="server" Height="100%"> |
| <uc1:ListUser ID="ListUser1" runat="server" Visible="false" /> |
| <uc2:EditUser ID="EditUser1" runat="server" Visible="false" /> |
| </telerik:RadPane> |
| </telerik:RadSplitter> |
| </telerik:RadPane> |
| </telerik:RadSplitter> |
| </form> |
| </body> |
| </html> |
| %@ Control Language="C#" AutoEventWireup="true" CodeFile="EditUser.ascx.cs" Inherits="EditUser" %> |
| <telerik:RadAjaxManagerProxy ID="RadAjaxManagerProxy1" runat="server"> |
| <AjaxSettings> |
| <telerik:AjaxSetting AjaxControlID="ButtonSaveSite"> |
| <UpdatedControls> |
| <telerik:AjaxUpdatedControl ControlID="RepeaterSite" UpdatePanelRenderMode="Block" /> |
| </UpdatedControls> |
| </telerik:AjaxSetting> |
| </AjaxSettings> |
| </telerik:RadAjaxManagerProxy> |
| <telerik:RadCodeBlock ID="RadCodeBlock1" runat="server"> |
| <script type="text/javascript"> |
| function UpdateItemCountField(sender, args) { |
| //set the footer text |
| sender.get_dropDownElement().lastChild.innerHTML = "A total of " + sender.get_items().get_count() + " items"; |
| } |
| function linckclick() { |
| alert("ok"); |
| } |
| </script> |
| </telerik:RadCodeBlock> |
| <br /> |
| <asp:Panel ID="Panel1" runat="server" HorizontalAlign="Center"> |
| <asp:Label ID="Label1" runat="server" Text="Choix de l'utilisateur" AssociatedControlID="RadComboBoxChoixUser"></asp:Label> |
| <telerik:RadComboBox ID="RadComboBoxChoixUser" runat="server" DropDownWidth="350px" |
| EmptyMessage="Choisir un utilisateur" EnableLoadOnDemand="true" EnableVirtualScrolling="false" |
| Height="150px" HighlightTemplatedItems="true" MarkFirstMatch="true" OnClientItemsRequested="UpdateItemCountField" |
| OnDataBound="RadComboBoxChoixUser_DataBound" OnItemDataBound="RadComboBoxChoixUser_ItemDataBound" |
| OnItemsRequested="RadComboBoxChoixUser_ItemsRequested" AllowCustomText="false" |
| Width="150px" AutoPostBack="True" OnSelectedIndexChanged="RadComboBoxChoixUser_SelectedIndexChanged"> |
| <HeaderTemplate> |
| <ul> |
| <li class="col2">Nom</li> |
| <li class="col3">Prénom</li> |
| <li class="col1">Pseudo</li> |
| </ul> |
| </HeaderTemplate> |
| <ItemTemplate> |
| <ul> |
| <li class="col2"> |
| <%# DataBinder.Eval(Container.DataItem, "LastName")%></li> |
| <li class="col3"> |
| <%# DataBinder.Eval(Container.DataItem, "FirstName")%></li> |
| <li class="col1"> |
| <%# DataBinder.Eval(Container.DataItem, "Users.UserName")%></li> |
| </ul> |
| </ItemTemplate> |
| <FooterTemplate> |
| A total of |
| <asp:Literal ID="RadComboItemsCount" runat="server" /> |
| items |
| </FooterTemplate> |
| </telerik:RadComboBox> |
| </asp:Panel> |
| <br /> |
| <telerik:RadTabStrip ID="RadTabStrip1" runat="server" MultiPageID="RadMultiPage1" Visible="false"> |
| <Tabs> |
| <telerik:RadTab runat="server" Text="Inforamtions générales" PageViewID="RadPageView1"> |
| </telerik:RadTab> |
| <telerik:RadTab runat="server" Text="Profile" PageViewID="RadPageView2"> |
| </telerik:RadTab> |
| <telerik:RadTab runat="server" Text="Droits" PageViewID="RadPageView3"> |
| </telerik:RadTab> |
| </Tabs> |
| </telerik:RadTabStrip> |
| <telerik:RadMultiPage ID="RadMultiPage1" runat="server"> |
| <telerik:RadPageView ID="RadPageView1" runat="server"> |
| <asp:Panel ID="Panel2" runat="server" GroupingText="Activation"> |
| <asp:Table ID="Table1" runat="server"> |
| <asp:TableRow> |
| <asp:TableCell Width="150"> |
| <asp:Label ID="Label2" runat="server" Text="Nom de compte" AssociatedControlID="LabelNomCompte"></asp:Label></asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:Label ID="LabelNomCompte" runat="server" Text=""></asp:Label></asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow> |
| <asp:TableCell Width="150"> |
| <asp:Label ID="Label3" runat="server" Text="Nom complet" AssociatedControlID="LabelNomComplet"></asp:Label></asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:Label ID="LabelNomComplet" runat="server" Text=""></asp:Label> |
| </asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow> |
| <asp:TableCell Width="150"> |
| <asp:Label ID="Label4" runat="server" Text="Activation" AssociatedControlID="CheckBoxActif"></asp:Label></asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:CheckBox ID="CheckBoxActif" runat="server" /></asp:TableCell> |
| </asp:TableRow> |
| </asp:Table> |
| </asp:Panel> |
| <asp:Panel ID="Panel3" runat="server" GroupingText="Utilisateur"> |
| <asp:Table ID="Table2" runat="server"> |
| <asp:TableRow> |
| <asp:TableCell Width="150"> |
| <asp:Label ID="Label5" runat="server" Text="Nom" AssociatedControlID="TextBoxNom"></asp:Label> |
| </asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:TextBox ID="TextBoxNom" runat="server"></asp:TextBox></asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow Width="150"> |
| <asp:TableCell> |
| <asp:Label ID="Label6" runat="server" Text="Prénom" AssociatedControlID="TextBoxPrenom"></asp:Label> |
| </asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:TextBox ID="TextBoxPrenom" runat="server"></asp:TextBox></asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow> |
| <asp:TableCell Width="150"> |
| <asp:Label ID="Label7" runat="server" Text="Email" AssociatedControlID="TextBoxEmail"></asp:Label></asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:TextBox ID="TextBoxEmail" runat="server"></asp:TextBox></asp:TableCell> |
| </asp:TableRow> |
| </asp:Table> |
| </asp:Panel> |
| <asp:Panel ID="Panel5" runat="server" GroupingText="Membre"> |
| <asp:Table ID="Table4" runat="server"> |
| <asp:TableRow> |
| <asp:TableCell Width="150">Société</asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:Label ID="LabelSoc" runat="server"></asp:Label></asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow> |
| <asp:TableCell Width="150">Groupe</asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:Label ID="LabelGroup" runat="server"></asp:Label></asp:TableCell> |
| </asp:TableRow> |
| </asp:Table> |
| </asp:Panel> |
| <asp:Panel ID="Panel4" runat="server" GroupingText="Authentification"> |
| <asp:Table ID="Table3" runat="server"> |
| <asp:TableRow> |
| <asp:TableCell Width="150">Nom de connexion</asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:TextBox ID="TextBoxLogin" runat="server"></asp:TextBox></asp:TableCell> |
| </asp:TableRow> |
| <asp:TableRow> |
| <asp:TableCell Width="150">Mot de passe</asp:TableCell> |
| <asp:TableCell>:</asp:TableCell> |
| <asp:TableCell> |
| <asp:HyperLink ID="HyperLink1" runat="server" onclick="javascript:linckclick();return false;" |
| Text="***** (Changement de mot de passe)" Font-Underline="false" ForeColor="Blue" |
| Style="cursor: pointer"></asp:HyperLink></asp:TableCell> |
| </asp:TableRow> |
| </asp:Table> |
| </asp:Panel> |
| </telerik:RadPageView> |
| <telerik:RadPageView ID="RadPageView2" runat="server"> |
| <asp:Panel ID="Panel6" runat="server" GroupingText="Sites"> |
| <asp:Repeater ID="RepeaterSite" runat="server" OnItemDataBound="RepeaterSite_ItemDataBound"> |
| <HeaderTemplate> |
| <table> |
| </HeaderTemplate> |
| <ItemTemplate> |
| <tr> |
| <td width="150"> |
| <asp:Label ID="LabelLibSite" runat="server" Text='<%#Eval("DataTextField") %>'></asp:Label> |
| <asp:HiddenField ID="HiddenFieldSite" runat="server" /> |
| </td> |
| <td> |
| : |
| </td> |
| <td> |
| <asp:CheckBox ID="CheckBoxSite" runat="server" /> |
| </td> |
| </tr> |
| </ItemTemplate> |
| <FooterTemplate> |
| </table> |
| </FooterTemplate> |
| </asp:Repeater> |
| <asp:Button ID="ButtonSaveSite" runat="server" Text="Sauvegarder" OnClick="ButtonSaveSite_Click" /> |
| </asp:Panel> |
| <asp:Panel ID="Panel7" runat="server" GroupingText="Numérotation Chrono"> |
| <asp:Repeater ID="RepeaterNumChrono" runat="server" OnItemDataBound="RepeaterNumChrono_ItemDataBound"> |
| <HeaderTemplate> |
| <table> |
| </HeaderTemplate> |
| <ItemTemplate> |
| <tr> |
| <td width="150"> |
| <asp:Label ID="LabelLibChrono" runat="server" Text='<%#Eval("DataTextField") %>'></asp:Label> |
| <asp:HiddenField ID="HiddenFieldChrono" runat="server" /> |
| </td> |
| <td> |
| : |
| </td> |
| <td> |
| <asp:CheckBox ID="CheckBoxChrono" runat="server" /> |
| </td> |
| </tr> |
| </ItemTemplate> |
| <FooterTemplate> |
| </table> |
| </FooterTemplate> |
| </asp:Repeater> |
| <asp:Button ID="ButtonSaveChrono" runat="server" Text="Sauvegarder" OnClick="ButtonSaveChrono_Click" /> |
| </asp:Panel> |
| </telerik:RadPageView> |
| <telerik:RadPageView ID="RadPageView3" runat="server"> |
| </telerik:RadPageView> |
| </telerik:RadMultiPage> |
protected void RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e) { string[] values = e.Argument.Split(new[] { "|" }, 2, StringSplitOptions.None); string nodeId = values[0]; string nodeText = values[1]; foreach (RadTreeNode node in GroupTree.Nodes) { if (UpdateNode(node, nodeId, nodeText)) break; } GroupTree.NodeExpand += (GroupTreeOnNodeExpand); } private static bool UpdateNode(RadTreeNode node, string nodeId, string nodeText) { if (node.Attributes["id"] == nodeId) { node.Text = nodeText; return true; } foreach (RadTreeNode childNode in node.Nodes) { if (UpdateNode(childNode, nodeId, nodeText)) return true; } return false; }
function onClientContextMenuItemClicking(sender, args)
{ var menuItem = args.get_menuItem(); var node = args.get_node(); menuItem.get_menu().hide(); switch (menuItem.get_value()) { case "SaveAs": Xlate.Web.Translation.service.ResourceFilesService.ExportResourceFile('108', PassServiceHandler, FailServiceHandler); break; } }[WebMethod()] public void ExportResourceFile(string fileId) { List<ISearchResult> searchResults; SearchCriteria searchCriteria; try { searchCriteria = new SearchCriteria(); searchCriteria.ResourceFileID = int.Parse(fileId); searchCriteria.SearchOption = SearchType.ResxKey; ResourceFile resourceFile = ResxFileManager.CreateResourceFile(searchCriteria); MemoryStream memoryStream = new MemoryStream(); memoryStream = Manager.GenerateResxSourceCode(resourceFile); memoryStream.Position = 0; DownloadFile(memoryStream,resourceFile.Name); } catch (Exception ex) { // set exception message string errorMessage = String.Format("Failed to export resource fileid ={0}, error:{1}", fileId ,ex.Message); // trace call TraceUtil.Write("ResourceFilesService::ExportResourceFile", "Exception occured [{0}]", errorMessage); // publish and rethrow the exception BusinessException businessExc = new BusinessException(errorMessage, ex); throw (businessExc); } } private void DownloadFile(MemoryStream memoryStream,string fileName) { byte[] byteArray = memoryStream.ToArray(); memoryStream.Flush(); memoryStream.Close(); HttpContext.Current.Response.Clear(); HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=test.resx"); HttpContext.Current.Response.AddHeader("Content-Length", byteArray.Length.ToString()); HttpContext.Current.Response.ContentType = "application/octet-stream"; HttpContext.Current.Response.BinaryWrite(byteArray); }