UpdatePanel triggers not firing - c#

I have problem with UpdatePanel (ASP.Net WebForms, .Net 4.0). Here is code:
<div class="container-fluid">
<form id="form1" runat="server">
<h2>Poruke</h2>
<div class="row">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
<asp:UpdatePanel ID="msgListUpdatePanel" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<div class="col-md-4">
<asp:ListBox ID="msgList" runat="server" OnSelectedIndexChanged="msgList_SelectedIndexChanged" AutoPostBack="true" ClientIDMode="AutoID"></asp:ListBox>
</div>
<div class="col-md-8">
<asp:ListBox ID="conversationList" runat="server" ClientIDMode="AutoID"></asp:ListBox>
<br class="divider" />
<p>
Odgovor: <span>
<asp:TextBox ID="replyTxtbox" runat="server"></asp:TextBox></span>
</p>
<asp:Button ID="sendBtn" runat="server" Text="PoĊĦalji" OnClick="sendBtn_Click" EnableViewState="false" ClientIDMode="AutoID" />
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="msgList" EventName="SelectedIndexChanged"/>
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</div>
and this is codebehind...
int userIdCookie = 0;
message selected = new message();
protected void Page_Load(object sender, EventArgs e)
{
if (!this.Page.User.Identity.IsAuthenticated)
{
FormsAuthentication.RedirectToLoginPage();
}
if (!Page.IsPostBack)
{
if (Int32.TryParse(HttpContext.Current.User.Identity.Name, out userIdCookie))
{
message msg = new message();
var allMsg = msg.allMessagesFormatted().Distinct().ToList();
msgList.DataSource = allMsg;
msgList.DataBind();
}
}
else
{
// test only!
replyTxtbox.Text = msgList.SelectedIndex.ToString();
msgListUpdatePanel.Update();
}
}
protected void msgList_SelectedIndexChanged(object sender, EventArgs e)
{
message msg = new message();
var allMsg = msg.allMessagesFormatted().Distinct().ToList();
msgList.DataSource = allMsg;
IList<message> boundList = (IList<message>)msgList.DataSource;
selected = boundList[msgList.SelectedIndex];
var conversation = msg.allMessagesFormatted().FindAll(x => x.conversationGuid == selected.conversationGuid);
conversationList.DataSource = conversation;
conversationList.DataBind();
}
protected void sendBtn_Click(object sender, EventArgs e)
{
if(selected.recipientId != 0)
{
message newmsg = new message();
newmsg.senderId = userIdCookie;
newmsg.recipientId = selected.recipientId;
newmsg.subject = selected.subject;
newmsg.messageTxt = replyTxtbox.Text;
newmsg.conversationGuid = selected.conversationGuid;
newmsg.time = DateTime.Now;
newmsg.Add();
}
}
msgList gets populated fine but when i change selection, nothing happens - its SelectedIndex event never fires. If I set AutoPostBack="true" to this listbox, it reloads page (which is exactly what I am trying to avoid).
To sum up - when i click on item in ListBox inside UpdatePanel, nothing happens (event isn't fired). I want to avoid page reload when selected index changes. I've tried dozen of solutions (ClientID, AsyncPostBack, "regular" PostBack triggers and I guess i missed one simple detail and it's driving me mad.
Can anyone help?
edit - as #mason pointed out, problem was in overidden message.ToString() method that contained \r\n chars which caused problems in postback.

You will receive a JavaScript error in your browser's console.
Uncaught Sys.WebForms.PageRequestManagerServerErrorException:
Sys.WebForms.PageRequestManagerServerErrorException: Invalid postback
or callback argument. Event validation is enabled using in configuration or <%# Page
EnableEventValidation="true" %> in a page. For security purposes,
this feature verifies that arguments to postback or callback events
originate from the server control that originally rendered them. If
the data is valid and expected, use the
ClientScriptManager.RegisterForEventValidation method in order to
register the postback or callback data for validation.
MsAjaxJs?v=c42ygB2U07n37m_Sfa8ZbLGVu4Rr2gsBo7MvUEnJeZ81:1 Uncaught
Sys.WebForms.PageRequestManagerServerErrorException:
Sys.WebForms.PageRequestManagerServerErrorException: Invalid postback
or callback argument. Event validation is enabled using in configuration or <%# Page
EnableEventValidation="true" %> in a page. For security purposes,
this feature verifies that arguments to postback or callback events
originate from the server control that originally rendered them. If
the data is valid and expected, use the
ClientScriptManager.RegisterForEventValidation method in order to
register the postback or callback data for validation.
You can see a simpler version if you use:
msgList.DataSource = new List<string>(){"A\r\n","B\r\n","C\r\n"};
When you watch it in the browser tab, you'll see POST request sent to the server, but on the server side the Page_Load method won't get hit at all.
The fix is either to not use \r\n characters in the data being used for the ListBox or to follow the directions to register it at ClientScriptManager.RegisterForEventValidation on MSDN.

Related

Jquery calendar does not reload after GridView is populated

I have a simple page with Jquery datepicker, UpdateProgress, and GridView inside of UpdatePanel.
Here is a fragment from the page:
...
Select From Date: <input type="text" id="datepickerfrom" name="datepickerfrom"/>
Select To Date: <input type="text" id="datepickerto" name="datepickerto"/>
<asp:Button ID="btnGetData" runat="server" OnClick="BtnGetData_Click" Text="Get Error List" />
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/ajax-loader.gif" />
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
...MyGrid...
</ContentTemplate>
</asp:UpdatePanel>
...
This is the code behind method invoked when clicking on the button:
protected void BtnGetData_Click(object sender, EventArgs e)
{
string dateFrom = HttpUtility.HtmlEncode(Request.Form["datepickerfrom"]);
string dateTo = HttpUtility.HtmlEncode(Request.Form["datepickerto"]);
InputData data = new InputData(dateFrom, dateTo);
Session["inputData"] = data;
gvErrorLog.PageIndex = 0;
LoadLogErrorData(data);
}
When I first load the page and click on one of the Date's text boxes, jQuery datepicker is poped up. When I refresh the page, it pops up as well.
However, after clicking on the button and populating the GridView with the data, it is not displayed anymore.
What can be the reason?
Your tag is
<input type="text" id="datepickerfrom" name="datepickerfrom"/>
This is really the regular html tag. Microsoft ASP.NET does NOT keep the state (ie in ViewState) of regular html tag. After postback, the page life cycle effectively creates a new instance of Page (System.Web.UI.Page) object before sending response back to browser as html.
On the other hand, once you change to
<asp:TextBox ID="datepickerfrom" runat="server" />
You will see it in postback. Also the way you capture those 2 dates in code behind is obsolete (only seen in ASP 1.1).
The namespace for your text tag is
System.Web.UI.HtmlControls.HtmlInputText and the namespace for the server tag is System.Web.UI.WebControls.TextBox. They belong to different namespaces. Any controls in the HtmlControls are for legacy purpose.
You may change to asp:TextBox and access them from code behind as follows:
protected void BtnGetData_Click(object sender, EventArgs e)
{
string dateFrom = datepickerfrom.Text; // -- updated
string dateTo = datepickerto.Text; // -- updated
InputData data = new InputData(dateFrom, dateTo);
Session["inputData"] = data;
gvErrorLog.PageIndex = 0;
LoadLogErrorData(data);
}
If you insist on your tags, you can add a hidden variable and update those hidden variable on change event of your textboxes.
I assume your textboxes are set up like the following
$(function () {
$("#<%=datepickerfrom.ClientID%>").datepicker();
$("#<%=datepickerto.ClientID%>").datepicker();
});
I finally found the answer to my problem here:
http://www.jquerybyexample.net/2010/08/jquery-datepicker-does-not-work-after.html

Unable to retrieve DDL SelectedValue bound in ASPX after Page Load

I have the following markup / code block in the ASPX file.
The binding of the ddl is triggered after Page_Load event which is in the code behind file.
This results me not able to get the selected value of the dropdownlist if I were to use such flow.
However for some purpose I require it to work this way.
Any idea how I could get the dropdownlist selected value when a post back is being triggered (click of the button)?
Page URL: page.aspx?para1=0&para2=value
ASPX PAGE
<%
if (Convert.ToInt32(Request.QueryString["para1"]) == 0)
{
ddl.DataValueField = "value";
ddl.DataTextField = "text";
ddl.DataSource = ds; //ds is valid, exact code not shown
ddl.DataBind();
} else {
//write in this area
Response.Write("Not 0");
}
%>
<form runat="server" id="user_form" class="form-horizontal">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<asp:UpdatePanel ID="updPanel" runat="server">
<ContentTemplate>
<asp:DropDownList runat="server" ID="ddl">
</asp:DropDownList>
<%-- this button will call btnSave_Click to get the ddl's value--%>
<asp:Button runat="server" ID="btn" Text="Button" OnClick="btn_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
CODE BEHIND
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//do my stuff
}
}
protected void btn_Click(object sender, EventArgs e)
{
int intValue = Convert.ToInt32(ddl.SelectedValue);
//do my stuff
}
The ASPX Page code block will run after Page_Load / page's lifecycle, then will determine what to do base on the url parameters.
Thanks in advance!
You could always throw in a hidden object and use jquery to copy the value to the hidden value based on a certain action without a postback and would do it client side like it sounds like you want it to do

OnClick and OnClientClick

I have an image button on a pop up page which is opened by another page
<asp:ImageButton
ID="Button_kalem_islemikaydet"
runat="server"
CausesValidation="False"
ImageUrl="~/images/butonlar/buyuk/Kaydet.jpg"
meta:resourcekey="Button_kalem_islemikaydetResource1"
OnClick="Button_ust_islemikaydet_Click"
OnClientClick="f2()"
Width="100" />
f2() is
<script type="text/javascript">
function f2() {
opener.document.getElementById("TextBox1").value = "hello world";
opener.document.getElementById("HiddenField1").value = "hello world";
window.opener.location.href = window.opener.location.href;
}
</script>
And Button_ust_islemikaydet_Click is another method implemented in aspx.cs file and it updates the database tables which are shown in the parent page in a GridView.
What I am trying to do is to doPostBack I mean refresh the opener(parent) page.And with these above codes refresh is working.However, parent page still shows the same data before the refresh.And the reason is that OnClientClick works before OnClick method
So my question is that is there any way I can run the method on OnClick and finish it and then run the OnClientClick method?
<form id="aspnetForm" runat="server">
<asp:Button Text="Click Me" ID="ClickMeButton" OnClick="ClickMeButton_OnClick" runat="server" />
<asp:HiddenField runat="server" ID="UpdateOpenerHiddenField" Value="false" />
<script type="text/javascript">
//1st approach
var updateOpenerField = window.document.getElementById("<%= UpdateOpenerHiddenField.ClientID %>");
if (updateOpenerField.value === "true") {
f2();
updateOpenerField.value = "false";
}
// for the 2nd approach just do nothing
function f2() {
alert("Hello, opener!");
}
</script>
</form>
protected void ClickMeButton_OnClick(object sender, EventArgs e)
{
//1st approach
UpdateOpenerHiddenField.Value = "true";
// 2nd approach
ClientScript.RegisterStartupScript(this.GetType(), "RefreshOpener", "f2();", true);
}
No, you can't run server side code (OnClick event handler) before client side. OnCLientClick event was added to perform some validation before post back. There is only one way to do it - update the f2 method and post data on server via ajax
You can put your javascript inside a PlaceHolder tag which you make visible in your server-side OnClick handler.
aspx code:
<asp:PlaceHolder id="refreshScript" visible="false" runat="server">
window.opener.location.href = window.opener.location.href;
window.close();
</asp:PlaceHolder
cs code:
protected void button_Click(Object sender, EventArgs e) {
// do whatever
refreshScript.Visible = true;
}

HttpRequestValidationException on PostBack within UpdatePanel

HttpRequestValidationException occurs when I try post when txtBulletin contains any HTML, like "Hello<br />World"
Bulletin.aspx
<asp:UpdatePanel ID="upContent" runat="server" UpdateMode="Always">
<ContentTemplate>
<div class="content bulletin-content">
<asp:TextBox ID="txtBulletin" runat="server"
TextMode="MultiLine" />
<div class="bulletin-edit">
<asp:ImageButton ID="btnSaveBulletin" runat="server"
ImageUrl="~/images/icons/check.gif"
CommandName="SaveChanges"
OnCommand="btnEditBulletin_Click"
Visible="false" />
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
Bulletin.aspx.cs
protected void btnEditBulletin_Click(object sender, CommandEventArgs e)
{
if (e.CommandName == "Edit")
{
// Do something
}
else if (e.CommandName == "SaveChanges")
{
// Do something
}
else if (e.CommandName == "Cancel")
{
// Do something
}
}
I have no idea how to bypass this, or why it evens does the validation for me. On error, the page no longer handles any PostBack events until I refresh the page.
ASP.NET checks POST values for potentially dangerous strings. This is done to prevent DoS attacks and the like.
To disable this, you'll need to edit the web.config file. Make sure the following element exists under <system.web>:
<pages validateRequest="false" />
Alternatively, to turn off request validation on a page-by-page basis, set the ValidateRequest property to false in the #Page declaration at the top of the ASPX page in question.
EDIT: Included details about how to turn request validation off for specific pages.

ASP.NET HoverMenuExtender Lazy Loading

I'm trying to get my hovermenuextenders to do some lazy loading. I have avatars across the site that when hovered over should pull back various things (images, recent posts, post count, etc) For obvious reasons I don't want to do this for all avatars on the page_load.
Using the following code I'm able to get the hover event to trigger a postback to the server asynchronously (breakpoint is hit onmouseover). However, the commands in the postback don't seem to be reflected after execution is done. The loading image/label stay in the hover panel. Any help is appreciated!
EDIT: I just realized that the very last avatar rendered on the page works properly but none of the ones above it do. Any ideas what might be causing this strange behavior?
<script language="javascript" type="text/javascript">
function OnHover(image) {
__doPostBack('<%= this.imageHoverTrigger.UniqueID %>', '');
}
</script>
<!-- DUMMY Hover Trigger -->
<input id="imageHoverTrigger" runat="server" style="display:none;"
type="button" onserverclick="imageHoverTrigger_Click" />
<!-- User Avatar -->
<div style="border: solid 1px #AAA; padding:2px; background-color:#fff;">
<asp:ImageButton ID="UserImg" runat="server" />
</div>
<!-- Hover tooltip disabled by default
(Explicitly enabled if needed)-->
<ajax:HoverMenuExtender ID="UserInfoHoverMenu" Enabled="false" runat="server"
OffsetX="-1"
OffsetY="3"
TargetControlID="UserImg"
PopupControlID="UserInfoPanel" dyn
HoverCssClass="userInfoHover"
PopupPosition="Bottom">
</ajax:HoverMenuExtender>
<!-- User Profile Info -->
<asp:Panel ID="UserInfoHover" runat="server" CssClass="userInfoPopupMenu">
<asp:UpdatePanel ID="UserInfoUpdatePanel" runat="server" UpdateMode="Conditional" >
<ContentTemplate>
<asp:Image ID="loadingImg" runat="server" ImageUrl="~/Design/images/ajax-loader-transp.gif" />
<asp:Label ID="loadingLbl" runat="server" Text="LOADING..." ></asp:Label>
<asp:Panel ID="UserInfo" runat="server" Visible="false">
<b><asp:Label ID="UserNameLbl" runat="server"></asp:Label><br /></b>
<span style="font-size:.8em">
<asp:Label ID="UserCityLbl" runat="server" Visible="false"></asp:Label> <asp:Label ID="UserStateLbl" runat="server" Visible="false"></asp:Label>
</span>
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="imageHoverTrigger" />
</Triggers>
</asp:UpdatePanel>
</asp:Panel>
And the code-behind:
protected void Page_Load(object sender, EventArgs e)
{
UserImg.Attributes.Add("onmouseover", "javascript:OnHover(this)");
}
protected void imageHoverTrigger_Click(object sender, EventArgs args)
{
// Hide loading image/label
loadingLbl.Visible = false;
loadingImg.Visible = false;
//TODO: Set user data here
UserInfo.Visible = true;
}
Figured it out:
My Page_Load event hookup should've been:
UserImg.Attributes.Add("onmouseover", "javascript:OnHover('" + this.imageHoverTrigger.UniqueID + "','" + this.hiddenLbl.ClientID + "')");
UserImg.Attributes.Add("onmouseout", "javascript:ClearTimer()");
and the javascript function should've been:
var hoverTimer;
// Called on the hover of the user image
function OnHover(trigger, hiddenTxt) {
var field = document.getElementById(hiddenTxt);
// Only post if this hover hasn't been done before
if (field == null || field.innerHTML == "false") {
hoverTimer = setTimeout(function() { ShowInfo(trigger) }, 500);
}
}
// Clears timeout onmouseout
function ClearTimer() {
clearTimeout(hoverTimer);
}
// Retrieves user info from server
function ShowInfo(trigger) {
__doPostBack(trigger, '');
}
I also added a hidden field on the form in order to know when the hover has been executed. The code behind sets the hidden field to true and my javascript checks for the value of the hidden field each time it executes. This stops the code from doing round trips each time the user hovers over the image.

Categories